import { useEffect, useMemo, useState } from 'react';
import { Modal, Pressable, ScrollView, StyleSheet, Text, View } from 'react-native';
import { router } from 'expo-router';
import { useTranslation } from 'react-i18next';
import {
  acceptDietMacros,
  commitDietPlan,
  createDietSession,
  fetchDietProfile,
  generateDietPlan,
  proposeDietMacros,
  regenerateDietMeal,
  saveDietProfile,
  toggleDietMealLock,
} from '@/src/api/diet-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 {
  DEFAULT_DIET_PROFILE,
  type DietGeneratorDraftMeal,
  type DietGeneratorSession,
  type DietUserProfile,
} from '@/src/types/generator';
import { MealCategory } from '@/src/types/recipe';
import { ApiError, extractApiError } from '@/src/utils/apiError';
import { categoryLabel } from '@/src/utils/recipe';

type Step = 'profile' | 'macros' | 'plan' | 'done';

function formatDraftMealMacros(meal: DietGeneratorDraftMeal): string {
  const parts = [`${meal.calories ?? '?'} kcal`];
  if (meal.proteinG != null) parts.push(`P ${meal.proteinG}g`);
  if (meal.fatG != null) parts.push(`F ${meal.fatG}g`);
  if (meal.carbsG != null) parts.push(`C ${meal.carbsG}g`);
  return parts.join(' · ');
}

export default function DietGeneratorScreen() {
  const { t } = useTranslation();
  const { colors } = useAppearance();
  const [step, setStep] = useState<Step>('profile');
  const [profile, setProfile] = useState<DietUserProfile>({ ...DEFAULT_DIET_PROFILE });
  const [sessionId, setSessionId] = useState<number | null>(null);
  const [session, setSession] = useState<DietGeneratorSession | null>(null);
  const [macros, setMacros] = useState({
    calories: 2000,
    proteinG: 150,
    fatG: 65,
    carbsG: 200,
    rationale: '',
  });
  const [commitResult, setCommitResult] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [info, setInfo] = useState<string | null>(null);
  const [loading, setLoading] = useState(false);
  const [previewMeal, setPreviewMeal] = useState<DietGeneratorDraftMeal | null>(null);

  useEffect(() => {
    void fetchDietProfile().then((p) => {
      if (p) setProfile({ ...DEFAULT_DIET_PROFILE, ...p });
    });
  }, []);

  const mealsByDate = useMemo(() => {
    const map = new Map<string, DietGeneratorSession['draftMeals']>();
    for (const meal of session?.draftMeals ?? []) {
      const list = map.get(meal.planDate) ?? [];
      list.push(meal);
      map.set(meal.planDate, list);
    }
    return [...map.entries()]
      .sort(([a], [b]) => a.localeCompare(b))
      .map(([date, meals]) => ({
        date,
        meals,
        summary: session?.daySummaries.find((d) => d.planDate === date),
      }));
  }, [session]);

  async function startSession() {
    setError(null);
    setLoading(true);
    try {
      await saveDietProfile(profile);
      const created = await createDietSession({ planDayCount: 7, calorieToleranceKcal: 10 });
      setSessionId(created.id);
      if (created.proposedMacros) applyMacros(created);
      const refined = await proposeDietMacros(created.id);
      if (refined.proposedMacros) applyMacros(refined);
      setStep('macros');
    } catch (e) {
      setError(extractApiError(e, t('generators.diet.error')));
    } finally {
      setLoading(false);
    }
  }

  async function acceptAndGenerate() {
    if (!sessionId) return;
    setError(null);
    setLoading(true);
    try {
      await acceptDietMacros(sessionId, macros);
      const plan = await generateDietPlan(sessionId);
      setSession(plan);
      setStep('plan');
    } catch (e) {
      setError(extractApiError(e, t('generators.diet.error')));
    } finally {
      setLoading(false);
    }
  }

  async function toggleLock(mealId: number, isLocked: boolean) {
    if (!sessionId) return;
    try {
      const updated = await toggleDietMealLock(sessionId, mealId, isLocked);
      setSession(updated);
    } catch (e) {
      setError(extractApiError(e, t('generators.diet.error')));
    }
  }

  async function regenMeal(planDate: string, mealCategory: number) {
    if (!sessionId) return;
    try {
      const updated = await regenerateDietMeal(sessionId, planDate, mealCategory);
      setSession(updated);
      setError(null);
      setInfo(null);
    } catch (e) {
      if (e instanceof ApiError && e.status === 400) {
        setInfo(t('generators.diet.noAlternativeMeals'));
        setError(null);
      } else {
        setError(extractApiError(e, t('generators.diet.error')));
        setInfo(null);
      }
    }
  }

  async function commitPlan() {
    if (!sessionId) return;
    setLoading(true);
    try {
      const result = await commitDietPlan(sessionId);
      setCommitResult(`${result.planStartDate} → ${result.planEndDate}`);
      setStep('done');
    } catch (e) {
      setError(extractApiError(e, t('generators.diet.error')));
    } finally {
      setLoading(false);
    }
  }

  function applyMacros(s: DietGeneratorSession) {
    if (!s.proposedMacros) return;
    setMacros({
      calories: s.proposedMacros.calories,
      proteinG: s.proposedMacros.proteinG,
      fatG: s.proposedMacros.fatG,
      carbsG: s.proposedMacros.carbsG,
      rationale: s.proposedMacros.rationale ?? '',
    });
  }

  function reset() {
    setStep('profile');
    setSessionId(null);
    setSession(null);
    setCommitResult(null);
    setError(null);
    setInfo(null);
  }

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

        {error ? (
          <View style={[styles.errorBox, { backgroundColor: colors.danger + '22' }]}>
            <Text style={{ color: colors.danger }}>{error}</Text>
          </View>
        ) : null}

        {step === 'profile' ? (
          <View style={[styles.card, { backgroundColor: colors.surface, borderColor: colors.border }]}>
            <Text style={[styles.sectionTitle, { color: colors.text }]}>
              {t('generators.diet.profileTitle')}
            </Text>
            <Input
              label={t('generators.diet.heightCm')}
              keyboardType="numeric"
              value={String(profile.heightCm)}
              onChangeText={(v) => setProfile({ ...profile, heightCm: Number(v) || 0 })}
            />
            <Input
              label={t('generators.diet.weightKg')}
              keyboardType="numeric"
              value={String(profile.weightKg)}
              onChangeText={(v) => setProfile({ ...profile, weightKg: Number(v) || 0 })}
            />
            <Input
              label={t('generators.diet.age')}
              keyboardType="numeric"
              value={String(profile.age)}
              onChangeText={(v) => setProfile({ ...profile, age: Number(v) || 0 })}
            />
            <Text style={[styles.label, { color: colors.text }]}>{t('generators.diet.sex')}</Text>
            <View style={styles.row}>
              {(['male', 'female'] as const).map((sex) => (
                <Pressable
                  key={sex}
                  onPress={() => setProfile({ ...profile, sex })}
                  style={[
                    styles.chip,
                    {
                      backgroundColor: profile.sex === sex ? colors.brand : colors.surface,
                      borderColor: profile.sex === sex ? colors.brand : colors.border,
                    },
                  ]}
                >
                  <Text style={{ color: profile.sex === sex ? '#fff' : colors.text }}>
                    {t(`generators.diet.${sex === 'male' ? 'male' : 'female'}`)}
                  </Text>
                </Pressable>
              ))}
            </View>
            <Text style={[styles.label, { color: colors.text }]}>{t('generators.diet.activity')}</Text>
            <View style={styles.wrapRow}>
              {(['sedentary', 'light', 'moderate', 'active', 'very_active'] as const).map((level) => (
                <Pressable
                  key={level}
                  onPress={() => setProfile({ ...profile, activityLevel: level })}
                  style={[
                    styles.chip,
                    {
                      backgroundColor: profile.activityLevel === level ? colors.brand : colors.surface,
                      borderColor: profile.activityLevel === level ? colors.brand : colors.border,
                    },
                  ]}
                >
                  <Text style={{ color: profile.activityLevel === level ? '#fff' : colors.text, fontSize: 12 }}>
                    {t(`generators.diet.${level === 'very_active' ? 'veryActive' : level}`)}
                  </Text>
                </Pressable>
              ))}
            </View>
            <Text style={[styles.label, { color: colors.text }]}>{t('generators.diet.goal')}</Text>
            <View style={styles.wrapRow}>
              {(['lose_weight', 'maintain', 'gain_muscle', 'recomp'] as const).map((goal) => (
                <Pressable
                  key={goal}
                  onPress={() => setProfile({ ...profile, goal })}
                  style={[
                    styles.chip,
                    {
                      backgroundColor: profile.goal === goal ? colors.brand : colors.surface,
                      borderColor: profile.goal === goal ? colors.brand : colors.border,
                    },
                  ]}
                >
                  <Text style={{ color: profile.goal === goal ? '#fff' : colors.text, fontSize: 12 }}>
                    {t(
                      `generators.diet.${
                        goal === 'lose_weight'
                          ? 'loseWeight'
                          : goal === 'gain_muscle'
                            ? 'gainMuscle'
                            : goal
                      }`,
                    )}
                  </Text>
                </Pressable>
              ))}
            </View>
            <Input
              label={t('generators.diet.allergies')}
              multiline
              value={profile.allergiesNotes ?? ''}
              onChangeText={(v) => setProfile({ ...profile, allergiesNotes: v })}
            />
            <Button title={t('generators.diet.continue')} loading={loading} onPress={() => void startSession()} />
          </View>
        ) : null}

        {step === 'macros' ? (
          <View style={[styles.card, { backgroundColor: colors.surface, borderColor: colors.border }]}>
            <Text style={[styles.sectionTitle, { color: colors.text }]}>
              {t('generators.diet.macrosTitle')}
            </Text>
            {macros.rationale ? (
              <Text style={{ color: colors.textMuted, marginBottom: 8 }}>{macros.rationale}</Text>
            ) : null}
            <Input
              label={t('manage.caloriesKcal')}
              keyboardType="numeric"
              value={String(macros.calories)}
              onChangeText={(v) => setMacros({ ...macros, calories: Number(v) || 0 })}
            />
            <Input
              label={t('manage.proteinG')}
              keyboardType="numeric"
              value={String(macros.proteinG)}
              onChangeText={(v) => setMacros({ ...macros, proteinG: Number(v) || 0 })}
            />
            <Input
              label={t('manage.fatG')}
              keyboardType="numeric"
              value={String(macros.fatG)}
              onChangeText={(v) => setMacros({ ...macros, fatG: Number(v) || 0 })}
            />
            <Input
              label={t('manage.carbsG')}
              keyboardType="numeric"
              value={String(macros.carbsG)}
              onChangeText={(v) => setMacros({ ...macros, carbsG: Number(v) || 0 })}
            />
            <View style={styles.buttonRow}>
              <Button title={t('common.back')} variant="secondary" onPress={() => setStep('profile')} />
              <Button
                title={t('generators.diet.acceptAndGenerate')}
                loading={loading}
                onPress={() => void acceptAndGenerate()}
              />
            </View>
          </View>
        ) : null}

        {step === 'plan' && session ? (
          <View style={styles.gap}>
            <Text style={{ color: colors.textMuted }}>{t('generators.diet.planHint')}</Text>
            {mealsByDate.map(({ date, meals, summary }) => (
              <View
                key={date}
                style={[styles.card, { backgroundColor: colors.surface, borderColor: colors.border }]}
              >
                <View style={styles.dayHeader}>
                  <Text style={[styles.sectionTitle, { color: colors.text }]}>{date}</Text>
                  <Text style={{ color: summary?.withinTolerance ? colors.brand : '#b45309' }}>
                    {summary?.totalCalories ?? 0} / {summary?.targetCalories ?? 0} kcal
                    {summary?.withinTolerance ? ' ✓' : ''}
                  </Text>
                </View>
                {meals.map((meal) => (
                  <View key={meal.id} style={[styles.mealRow, { borderColor: colors.border }]}>
                    <View style={{ flex: 1 }}>
                      <Text style={{ color: colors.textMuted, fontSize: 11, textTransform: 'uppercase' }}>
                        {categoryLabel(meal.mealCategory as MealCategory, t)}
                      </Text>
                      <Text style={{ color: colors.text, fontWeight: '600' }}>{meal.recipeName}</Text>
                      <Text style={{ color: colors.textMuted, fontSize: 12 }}>
                        {formatDraftMealMacros(meal)}
                      </Text>
                    </View>
                    <View style={styles.mealActions}>
                      <Button
                        title={t('generators.diet.viewRecipe')}
                        variant="secondary"
                        onPress={() => setPreviewMeal(meal)}
                        style={styles.smallBtn}
                      />
                      <Button
                        title={meal.isLocked ? t('generators.diet.unlock') : t('generators.diet.lock')}
                        variant="secondary"
                        onPress={() => void toggleLock(meal.id, !meal.isLocked)}
                        style={styles.smallBtn}
                      />
                      <Button
                        title="↻"
                        variant="secondary"
                        disabled={meal.isLocked}
                        onPress={() => void regenMeal(meal.planDate, meal.mealCategory)}
                        style={styles.smallBtn}
                      />
                    </View>
                  </View>
                ))}
              </View>
            ))}
            <Button title={t('generators.diet.commit')} loading={loading} onPress={() => void commitPlan()} />
          </View>
        ) : null}

        {step === 'done' ? (
          <View style={[styles.card, { backgroundColor: colors.surface, borderColor: colors.border }]}>
            <Text style={[styles.sectionTitle, { color: colors.brand }]}>{t('generators.diet.done')}</Text>
            {commitResult ? <Text style={{ color: colors.textMuted }}>{commitResult}</Text> : null}
            <Button title={t('nav.planner')} onPress={() => router.push('/(main)/(tabs)/planner')} />
            <Button title={t('generators.diet.newPlan')} variant="secondary" onPress={reset} />
          </View>
        ) : null}
      </ScrollView>

      <Modal visible={!!previewMeal} transparent animationType="slide" onRequestClose={() => setPreviewMeal(null)}>
        <View style={styles.modalBackdrop}>
          <View style={[styles.modalCard, { backgroundColor: colors.surface, borderColor: colors.border }]}>
            <ScrollView contentContainerStyle={styles.modalScroll}>
              {previewMeal ? (
                <>
                  <Text style={[styles.sectionTitle, { color: colors.text }]}>{previewMeal.recipeName}</Text>
                  {previewMeal.calories != null ? (
                    <Text style={{ color: colors.textMuted, marginBottom: 8 }}>
                      {previewMeal.calories} kcal · P {previewMeal.proteinG ?? 0}g · F {previewMeal.fatG ?? 0}g · C{' '}
                      {previewMeal.carbsG ?? 0}g
                    </Text>
                  ) : null}
                  <Text style={[styles.label, { color: colors.text }]}>{t('recipes.ingredients')}</Text>
                  {previewMeal.ingredients.map((ing) => (
                    <Text key={ing.id} style={{ color: colors.text, marginBottom: 4 }}>
                      • {ing.name}
                      {ing.amountGrams != null ? ` — ${ing.amountGrams}g` : ''}
                      {ing.unit ? ` ${ing.unit}` : ''}
                    </Text>
                  ))}
                  <Text style={[styles.label, { color: colors.text, marginTop: 12 }]}>
                    {t('recipes.preparation')}
                  </Text>
                  {previewMeal.steps.map((step) => (
                    <Text key={step.id} style={{ color: colors.text, marginBottom: 4 }}>
                      {step.stepNumber}. {step.description}
                    </Text>
                  ))}
                </>
              ) : null}
            </ScrollView>
            <Button title={t('common.back')} variant="secondary" onPress={() => setPreviewMeal(null)} />
          </View>
        </View>
      </Modal>
    </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' },
  row: { flexDirection: 'row', gap: 8 },
  wrapRow: { flexDirection: 'row', flexWrap: 'wrap', gap: 8 },
  chip: { borderWidth: 1, borderRadius: 999, paddingHorizontal: 12, paddingVertical: 8 },
  buttonRow: { gap: 10 },
  gap: { gap: 12 },
  dayHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', gap: 8 },
  mealRow: {
    borderTopWidth: 1,
    paddingTop: 10,
    marginTop: 10,
    flexDirection: 'row',
    alignItems: 'center',
    gap: 8,
  },
  mealActions: { gap: 6 },
  smallBtn: { minHeight: 36, paddingHorizontal: 10 },
  errorBox: { borderRadius: 12, padding: 12 },
  infoBox: { borderRadius: 12, padding: 12 },
  modalBackdrop: {
    flex: 1,
    backgroundColor: 'rgba(0,0,0,0.5)',
    justifyContent: 'flex-end',
    padding: 16,
  },
  modalCard: {
    borderWidth: 1,
    borderRadius: 16,
    padding: 16,
    maxHeight: '85%',
    gap: 12,
  },
  modalScroll: { gap: 4, paddingBottom: 8 },
});
