import { useMemo, useState } from 'react';
import { Pressable, ScrollView, StyleSheet, Text, View } from 'react-native';
import { router } from 'expo-router';
import { useTranslation } from 'react-i18next';
import {
  commitRecipes,
  createRecipeSession,
  generateRecipeDrafts,
  regenerateRecipePart,
  removeRecipeDraft,
} from '@/src/api/recipe-generator.api';
import { Button } from '@/src/components/Button';
import { Input } from '@/src/components/Input';
import { Screen } from '@/src/components/Screen';
import { useAppearance } from '@/src/context/AppearanceContext';
import type { CommitRecipeResult, GeneratedRecipeDraft, RecipeGeneratorConstraints } from '@/src/types/generator';
import { MealCategory } from '@/src/types/recipe';
import { extractApiError } from '@/src/utils/apiError';
import { ALL_CATEGORIES, categoryLabel } from '@/src/utils/recipe';

type Step = 'constraints' | 'review' | 'done';

export default function RecipeGeneratorScreen() {
  const { t } = useTranslation();
  const { colors } = useAppearance();
  const [step, setStep] = useState<Step>('constraints');
  const [sessionId, setSessionId] = useState<number | null>(null);
  const [drafts, setDrafts] = useState<GeneratedRecipeDraft[]>([]);
  const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set());
  const [savedRecipes, setSavedRecipes] = useState<CommitRecipeResult[]>([]);
  const [recipeCount, setRecipeCount] = useState('3');
  const [pending, setPending] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [constraints, setConstraints] = useState<RecipeGeneratorConstraints>({
    prompt: '',
    mealCategory: MealCategory.Breakfast,
    targetCalories: null,
    calorieToleranceKcal: 10,
    maxPrepTimeMinutes: 30,
    cuisineStyle: '',
    dietStyle: '',
    exclusions: '',
  });

  const calorieTolerance = constraints.calorieToleranceKcal ?? 10;

  function isWithinCalorieTarget(calories?: number | null): boolean {
    if (!constraints.targetCalories || calories == null) return true;
    return Math.abs(calories - constraints.targetCalories) <= calorieTolerance;
  }

  const allSelected = useMemo(
    () => drafts.length > 0 && drafts.every((d) => selectedIds.has(d.draftId)),
    [drafts, selectedIds],
  );

  function syncDrafts(next: GeneratedRecipeDraft[]) {
    setDrafts(next);
    setSelectedIds(new Set(next.map((d) => d.draftId)));
  }

  async function runGenerate() {
    setError(null);
    setPending(true);
    const count = Math.min(8, Math.max(1, Number(recipeCount) || 3));
    try {
      let session;
      if (sessionId) {
        session = await generateRecipeDrafts(sessionId, count);
      } else {
        const created = await createRecipeSession(constraints);
        setSessionId(created.id);
        session = await generateRecipeDrafts(created.id, count);
      }
      syncDrafts(session.drafts ?? []);
      setStep('review');
    } catch (e) {
      setError(extractApiError(e, t('generators.recipe.error')));
    } finally {
      setPending(false);
    }
  }

  async function regen(draftId: string, mode: 'ingredients' | 'steps' | 'full') {
    if (!sessionId) return;
    setPending(true);
    setError(null);
    try {
      const session = await regenerateRecipePart(sessionId, draftId, mode, constraints.prompt);
      syncDrafts(session.drafts ?? []);
    } catch (e) {
      setError(extractApiError(e, t('generators.recipe.error')));
    } finally {
      setPending(false);
    }
  }

  async function removeDraft(draftId: string) {
    if (!sessionId) return;
    setPending(true);
    setError(null);
    try {
      const session = await removeRecipeDraft(sessionId, draftId);
      const next = session.drafts ?? [];
      syncDrafts(next);
      if (next.length === 0) setStep('constraints');
    } catch (e) {
      setError(extractApiError(e, t('generators.recipe.error')));
    } finally {
      setPending(false);
    }
  }

  async function saveSelected() {
    if (!sessionId || selectedIds.size === 0) return;
    setPending(true);
    setError(null);
    try {
      const result = await commitRecipes(sessionId, [...selectedIds]);
      setSavedRecipes(result.saved);
      const remaining = drafts.filter((d) => !selectedIds.has(d.draftId));
      if (remaining.length === 0) setStep('done');
      else syncDrafts(remaining);
    } catch (e) {
      setError(extractApiError(e, t('generators.recipe.error')));
    } finally {
      setPending(false);
    }
  }

  function toggleSelected(draftId: string) {
    setSelectedIds((prev) => {
      const next = new Set(prev);
      if (next.has(draftId)) next.delete(draftId);
      else next.add(draftId);
      return next;
    });
  }

  function toggleAll() {
    setSelectedIds(allSelected ? new Set() : new Set(drafts.map((d) => d.draftId)));
  }

  return (
    <Screen title={t('generators.recipe.title')} subtitle={t('generators.recipe.subtitle')}>
      <ScrollView contentContainerStyle={styles.scroll}>
        {error ? (
          <View style={[styles.errorBox, { backgroundColor: colors.danger + '22' }]}>
            <Text style={{ color: colors.danger }}>{error}</Text>
          </View>
        ) : null}

        {step === 'constraints' ? (
          <View style={[styles.card, { backgroundColor: colors.surface, borderColor: colors.border }]}>
            <Text style={[styles.sectionTitle, { color: colors.text }]}>
              {t('generators.recipe.constraintsTitle')}
            </Text>
            <Input
              label={t('generators.recipe.prompt')}
              multiline
              placeholder={t('generators.recipe.promptPlaceholder')}
              value={constraints.prompt}
              onChangeText={(v) => setConstraints({ ...constraints, prompt: v })}
            />
            <Input
              label={t('generators.recipe.targetCalories')}
              keyboardType="numeric"
              placeholder={t('generators.recipe.targetCaloriesOptional')}
              value={constraints.targetCalories != null ? String(constraints.targetCalories) : ''}
              onChangeText={(v) =>
                setConstraints({
                  ...constraints,
                  targetCalories: v.trim() ? Number(v) || null : null,
                })
              }
            />
            <Text style={{ color: colors.textMuted, fontSize: 12, marginBottom: 12 }}>
              {t('generators.recipe.targetCaloriesHint')}
            </Text>
            <Input
              label={t('generators.recipe.recipeCount')}
              keyboardType="numeric"
              value={recipeCount}
              onChangeText={setRecipeCount}
            />
            <Text style={[styles.label, { color: colors.text }]}>{t('common.category')}</Text>
            <View style={styles.wrapRow}>
              {ALL_CATEGORIES.map((cat) => (
                <Pressable
                  key={cat}
                  onPress={() => setConstraints({ ...constraints, mealCategory: cat })}
                  style={[
                    styles.chip,
                    {
                      backgroundColor: constraints.mealCategory === cat ? colors.brand : colors.surface,
                      borderColor: constraints.mealCategory === cat ? colors.brand : colors.border,
                    },
                  ]}
                >
                  <Text style={{ color: constraints.mealCategory === cat ? '#fff' : colors.text, fontSize: 12 }}>
                    {categoryLabel(cat, t)}
                  </Text>
                </Pressable>
              ))}
            </View>
            <Input
              label={t('generators.recipe.maxPrep')}
              keyboardType="numeric"
              value={String(constraints.maxPrepTimeMinutes ?? '')}
              onChangeText={(v) =>
                setConstraints({ ...constraints, maxPrepTimeMinutes: Number(v) || undefined })
              }
            />
            <Input
              label={t('generators.recipe.exclusions')}
              value={constraints.exclusions ?? ''}
              onChangeText={(v) => setConstraints({ ...constraints, exclusions: v })}
            />
            <Button
              title={t('generators.recipe.generate')}
              loading={pending}
              disabled={!constraints.prompt.trim()}
              onPress={() => void runGenerate()}
            />
          </View>
        ) : null}

        {step === 'review' && drafts.length > 0 ? (
          <View style={styles.gap}>
            <View style={styles.rowBetween}>
              <Text style={{ color: colors.textMuted, flex: 1 }}>
                {t('generators.recipe.reviewHint', { count: drafts.length })}
              </Text>
              <Pressable onPress={toggleAll} style={styles.selectAll}>
                <Text style={{ color: colors.brand, fontWeight: '600' }}>
                  {t('generators.recipe.selectAll')}
                </Text>
              </Pressable>
            </View>

            {drafts.map((draft) => (
              <View
                key={draft.draftId}
                style={[styles.card, { backgroundColor: colors.surface, borderColor: colors.border }]}
              >
                <View style={styles.rowBetween}>
                  <Pressable onPress={() => toggleSelected(draft.draftId)} style={styles.checkRow}>
                    <View
                      style={[
                        styles.checkbox,
                        {
                          borderColor: selectedIds.has(draft.draftId) ? colors.brand : colors.border,
                          backgroundColor: selectedIds.has(draft.draftId) ? colors.brand : 'transparent',
                        },
                      ]}
                    />
                    <View style={{ flex: 1 }}>
                      <Text style={[styles.sectionTitle, { color: colors.text }]}>{draft.name}</Text>
                      {draft.calories != null ? (
                        <Text
                          style={{
                            color:
                              constraints.targetCalories && !isWithinCalorieTarget(draft.calories)
                                ? '#b45309'
                                : colors.textMuted,
                            fontSize: 13,
                          }}
                        >
                          {constraints.targetCalories
                            ? t('generators.recipe.caloriesWithTarget', {
                                actual: draft.calories,
                                target: constraints.targetCalories,
                              })
                            : `${draft.calories} kcal`}
                          {' · '}
                          P {draft.protein ?? 0}g · F {draft.fat ?? 0}g · C {draft.carbs ?? 0}g
                        </Text>
                      ) : null}
                    </View>
                  </Pressable>
                </View>

                {draft.unlinkedIngredientCount > 0 ? (
                  <Text style={{ color: '#b45309' }}>
                    {t('generators.recipe.unlinkedWarning', { count: draft.unlinkedIngredientCount })}
                  </Text>
                ) : null}

                <Text style={[styles.label, { color: colors.text }]}>{t('recipes.ingredients')}</Text>
                {draft.ingredients.map((ing, i) => (
                  <Text
                    key={i}
                    style={{ color: !ing.isLinked && ing.amountGrams ? '#b45309' : colors.text, fontSize: 14 }}
                  >
                    {ing.name} — {ing.amountGrams ?? '?'}g {ing.unit ?? ''}
                  </Text>
                ))}

                <Text style={[styles.label, { color: colors.text, marginTop: 8 }]}>
                  {t('manage.preparationSteps')}
                </Text>
                {draft.steps.map((s) => (
                  <Text key={s.stepNumber} style={{ color: colors.text, fontSize: 14 }}>
                    {s.stepNumber}. {s.description}
                  </Text>
                ))}

                <View style={styles.gap}>
                  <Button
                    title={t('generators.recipe.regenIngredients')}
                    variant="secondary"
                    loading={pending}
                    onPress={() => void regen(draft.draftId, 'ingredients')}
                  />
                  <Button
                    title={t('generators.recipe.remove')}
                    variant="danger"
                    disabled={pending}
                    onPress={() => void removeDraft(draft.draftId)}
                  />
                </View>
              </View>
            ))}

            <Button
              title={t('generators.recipe.saveSelected', { count: selectedIds.size })}
              loading={pending}
              disabled={selectedIds.size === 0}
              onPress={() => void saveSelected()}
            />
            <Button title={t('common.back')} variant="secondary" onPress={() => setStep('constraints')} />
          </View>
        ) : null}

        {step === 'done' && savedRecipes.length > 0 ? (
          <View style={[styles.card, { backgroundColor: colors.surface, borderColor: colors.border }]}>
            <Text style={[styles.sectionTitle, { color: colors.text }]}>
              {t('generators.recipe.doneMultiple', { count: savedRecipes.length })}
            </Text>
            {savedRecipes.map((r) => (
              <Pressable key={r.recipeId} onPress={() => router.push(`/(main)/recipe/${r.recipeId}`)}>
                <Text style={{ color: colors.brand, fontSize: 16, marginBottom: 8 }}>{r.recipeName}</Text>
              </Pressable>
            ))}
            <Button
              title={t('generators.recipe.generateMore')}
              variant="secondary"
              onPress={() => {
                setStep('constraints');
                setDrafts([]);
                setSelectedIds(new Set());
                setSavedRecipes([]);
                setSessionId(null);
              }}
            />
          </View>
        ) : null}
      </ScrollView>
    </Screen>
  );
}

const styles = StyleSheet.create({
  scroll: { gap: 16, paddingBottom: 32 },
  card: { borderWidth: 1, borderRadius: 16, padding: 16, gap: 12 },
  sectionTitle: { fontSize: 18, fontWeight: '700' },
  label: { fontSize: 14, fontWeight: '600' },
  wrapRow: { flexDirection: 'row', flexWrap: 'wrap', gap: 8 },
  chip: { borderWidth: 1, borderRadius: 999, paddingHorizontal: 12, paddingVertical: 8 },
  gap: { gap: 10 },
  rowBetween: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', gap: 8 },
  checkRow: { flexDirection: 'row', alignItems: 'flex-start', gap: 10, flex: 1 },
  checkbox: { width: 22, height: 22, borderRadius: 6, borderWidth: 2, marginTop: 2 },
  selectAll: { paddingVertical: 4, paddingHorizontal: 8 },
  errorBox: { borderRadius: 12, padding: 12 },
});
