import { useEffect, useMemo, useState } from 'react';
import { Alert, Pressable, ScrollView, StyleSheet, Text, View } from 'react-native';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';
import {
  createIngredientCatalogItem,
  deleteIngredientCatalogItem,
  fetchIngredientCatalogItems,
  fetchIngredientCategories,
  updateIngredientCatalogItem,
} from '@/src/api/ingredient-catalog.api';
import { Button } from '@/src/components/Button';
import { ErrorView } from '@/src/components/ErrorView';
import { Input } from '@/src/components/Input';
import { Screen } from '@/src/components/Screen';
import { useAppearance } from '@/src/context/AppearanceContext';
import type {
  IngredientCategory,
  IngredientNutritionItem,
  UpsertIngredientNutritionItemInput,
} from '@/src/types/ingredient-catalog';
import { extractApiError } from '@/src/utils/apiError';
import { ingredientDisplayName } from '@/src/utils/ingredient-catalog.util';
import { nextSort, sortBy, sortIndicator, type SortDirection } from '@/src/utils/sort';

type IngredientSortColumn = 'name' | 'category' | 'calories' | 'protein' | 'fat' | 'carbs' | 'fiber';

const EMPTY_FORM: UpsertIngredientNutritionItemInput = {
  categoryId: 0,
  name: '',
  namePl: '',
  caloriesPer100G: 0,
  proteinGPer100G: 0,
  fatGPer100G: 0,
  carbsGPer100G: 0,
  fiberGPer100G: null,
  sortOrder: 0,
  isActive: true,
};

export default function IngredientsScreen() {
  const { t, i18n } = useTranslation();
  const { colors } = useAppearance();
  const queryClient = useQueryClient();
  const [category, setCategory] = useState('');
  const [search, setSearch] = useState('');
  const [debouncedSearch, setDebouncedSearch] = useState('');
  const [showForm, setShowForm] = useState(false);
  const [editingId, setEditingId] = useState<number | null>(null);
  const [form, setForm] = useState<UpsertIngredientNutritionItemInput>({ ...EMPTY_FORM });
  const [formError, setFormError] = useState<string | null>(null);
  const [sort, setSort] = useState<{ column: IngredientSortColumn; direction: SortDirection }>({
    column: 'name',
    direction: 'asc',
  });

  useEffect(() => {
    const timer = setTimeout(() => setDebouncedSearch(search.trim()), 300);
    return () => clearTimeout(timer);
  }, [search]);

  const categoriesQuery = useQuery({
    queryKey: ['ingredient-categories'],
    queryFn: fetchIngredientCategories,
  });

  const itemsQuery = useQuery({
    queryKey: ['ingredient-catalog', category, debouncedSearch],
    queryFn: () =>
      fetchIngredientCatalogItems({
        category: category || undefined,
        search: debouncedSearch || undefined,
      }),
  });

  const saveMutation = useMutation({
    mutationFn: async () => {
      const payload = {
        ...form,
        name: form.name.trim(),
        namePl: form.namePl?.trim() || null,
        fiberGPer100G: form.fiberGPer100G ?? null,
      };
      if (editingId) return updateIngredientCatalogItem(editingId, payload);
      return createIngredientCatalogItem(payload);
    },
    onSuccess: () => {
      setShowForm(false);
      setEditingId(null);
      setFormError(null);
      void queryClient.invalidateQueries({ queryKey: ['ingredient-categories'] });
      void queryClient.invalidateQueries({ queryKey: ['ingredient-catalog'] });
    },
    onError: (err) => {
      setFormError(extractApiError(err, t('errors.saveIngredientFailed')));
    },
  });

  const deleteMutation = useMutation({
    mutationFn: deleteIngredientCatalogItem,
    onSuccess: () => {
      void queryClient.invalidateQueries({ queryKey: ['ingredient-categories'] });
      void queryClient.invalidateQueries({ queryKey: ['ingredient-catalog'] });
    },
  });

  const categoryLabel = (code: string, fallback: string) =>
    t(`ingredientCatalog.categories.${code}`, { defaultValue: fallback });

  const totalCount = useMemo(
    () => (categoriesQuery.data ?? []).reduce((sum, c) => sum + c.itemCount, 0),
    [categoriesQuery.data],
  );

  const openCreateForm = () => {
    setEditingId(null);
    setForm({ ...EMPTY_FORM, categoryId: categoriesQuery.data?.[0]?.id ?? 0 });
    setFormError(null);
    setShowForm(true);
  };

  const openEditForm = (item: IngredientNutritionItem) => {
    setEditingId(item.id);
    setForm({
      categoryId: item.categoryId,
      name: item.name,
      namePl: item.namePl ?? '',
      caloriesPer100G: item.caloriesPer100G,
      proteinGPer100G: item.proteinGPer100G,
      fatGPer100G: item.fatGPer100G,
      carbsGPer100G: item.carbsGPer100G,
      fiberGPer100G: item.fiberGPer100G,
      sortOrder: 0,
      isActive: true,
    });
    setFormError(null);
    setShowForm(true);
  };

  const saveForm = () => {
    if (!form.categoryId || !form.name.trim()) {
      setFormError(t('ingredientCatalog.formInvalid'));
      return;
    }
    saveMutation.mutate();
  };

  const deleteItem = (id: number) => {
    Alert.alert(t('common.delete'), t('ingredientCatalog.deleteConfirm'), [
      { text: t('common.cancel'), style: 'cancel' },
      { text: t('common.delete'), style: 'destructive', onPress: () => deleteMutation.mutate(id) },
    ]);
  };

  const loading = categoriesQuery.isLoading || itemsQuery.isLoading;
  const error = categoriesQuery.error ?? itemsQuery.error;
  const items = itemsQuery.data ?? [];

  const sortedItems = useMemo(() => {
    const { column, direction } = sort;
    return sortBy(items, direction, (item) => {
      switch (column) {
        case 'name':
          return ingredientDisplayName(item, i18n.language);
        case 'category':
          return item.categoryCode;
        case 'calories':
          return item.caloriesPer100G;
        case 'protein':
          return Number(item.proteinGPer100G);
        case 'fat':
          return Number(item.fatGPer100G);
        case 'carbs':
          return Number(item.carbsGPer100G);
        case 'fiber':
          return item.fiberGPer100G != null ? Number(item.fiberGPer100G) : null;
      }
    });
  }, [items, sort, i18n.language]);

  const toggleSort = (column: IngredientSortColumn) => {
    setSort((current) => nextSort(current, column));
  };

  return (
    <Screen
      title={t('ingredientCatalog.title')}
      subtitle={t('ingredientCatalog.subtitle')}
      loading={loading}
    >
      <Button title={`+ ${t('ingredientCatalog.addIngredient')}`} variant="secondary" onPress={openCreateForm} />

      {showForm ? (
        <View style={[styles.formBox, { borderColor: colors.border, backgroundColor: colors.surface }]}>
          <Text style={[styles.formTitle, { color: colors.text }]}>
            {editingId ? t('ingredientCatalog.editIngredient') : t('ingredientCatalog.addIngredient')}
          </Text>
          {formError ? <Text style={{ color: '#dc2626', marginBottom: 8 }}>{formError}</Text> : null}
          <Text style={[styles.label, { color: colors.text }]}>{t('ingredientCatalog.columns.category')}</Text>
          <ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles.chips}>
            {(categoriesQuery.data ?? []).map((cat: IngredientCategory) => (
              <Chip
                key={cat.id}
                label={categoryLabel(cat.code, cat.name)}
                active={form.categoryId === cat.id}
                onPress={() => setForm((prev) => ({ ...prev, categoryId: cat.id }))}
              />
            ))}
          </ScrollView>
          <Input
            label={t('ingredientCatalog.nameEn')}
            value={form.name}
            onChangeText={(v) => setForm((prev) => ({ ...prev, name: v }))}
          />
          <Input
            label={t('ingredientCatalog.namePlLabel')}
            value={form.namePl ?? ''}
            onChangeText={(v) => setForm((prev) => ({ ...prev, namePl: v }))}
          />
          {(
            [
              ['caloriesPer100G', 'ingredientCatalog.columns.calories'],
              ['proteinGPer100G', 'ingredientCatalog.columns.protein'],
              ['fatGPer100G', 'ingredientCatalog.columns.fat'],
              ['carbsGPer100G', 'ingredientCatalog.columns.carbs'],
              ['fiberGPer100G', 'ingredientCatalog.columns.fiber'],
            ] as const
          ).map(([key, labelKey]) => (
            <Input
              key={key}
              label={t(labelKey)}
              keyboardType="decimal-pad"
              value={form[key]?.toString() ?? ''}
              onChangeText={(v) =>
                setForm((prev) => ({
                  ...prev,
                  [key]: v === '' ? null : Number(v),
                }))
              }
            />
          ))}
          <View style={styles.formActions}>
            <Button title={t('common.save')} loading={saveMutation.isPending} onPress={saveForm} />
            <Button title={t('common.cancel')} variant="secondary" onPress={() => setShowForm(false)} />
          </View>
        </View>
      ) : null}

      <ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles.chips}>
        <Chip
          label={`${t('ingredientCatalog.allCategories')} (${totalCount})`}
          active={category === ''}
          onPress={() => setCategory('')}
        />
        {(categoriesQuery.data ?? []).map((cat: IngredientCategory) => (
          <Chip
            key={cat.code}
            label={`${categoryLabel(cat.code, cat.name)} (${cat.itemCount})`}
            active={category === cat.code}
            onPress={() => setCategory(cat.code)}
          />
        ))}
      </ScrollView>

      <Input
        label={t('common.search')}
        value={search}
        onChangeText={setSearch}
        placeholder={t('ingredientCatalog.searchPlaceholder')}
      />

      {(itemsQuery.data ?? []).length > 0 ? (
        <ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles.sortRow}>
          {(
            [
              ['name', 'ingredientCatalog.columns.name'],
              ['category', 'ingredientCatalog.columns.category'],
              ['calories', 'ingredientCatalog.columns.calories'],
              ['protein', 'ingredientCatalog.columns.protein'],
              ['fat', 'ingredientCatalog.columns.fat'],
              ['carbs', 'ingredientCatalog.columns.carbs'],
              ['fiber', 'ingredientCatalog.columns.fiber'],
            ] as const
          ).map(([column, labelKey]) => (
            <SortChip
              key={column}
              label={`${t(labelKey)}${sortIndicator(sort, column)}`}
              active={sort.column === column}
              onPress={() => toggleSort(column)}
            />
          ))}
        </ScrollView>
      ) : null}

      {error ? (
        <ErrorView
          message={extractApiError(error, t('errors.loadIngredientCatalogFailed'))}
          onRetry={() => {
            categoriesQuery.refetch();
            itemsQuery.refetch();
          }}
        />
      ) : (itemsQuery.data ?? []).length === 0 ? (
        <View style={styles.empty}>
          <Text style={[styles.emptyTitle, { color: colors.text }]}>{t('ingredientCatalog.noResultsTitle')}</Text>
          <Text style={{ color: colors.textMuted }}>{t('ingredientCatalog.noResultsDescription')}</Text>
        </View>
      ) : (
        <ScrollView contentContainerStyle={styles.list}>
          {sortedItems.map((item) => (
            <View
              key={item.id}
              style={[styles.card, { backgroundColor: colors.surface, borderColor: colors.border }]}
            >
              <View style={styles.cardHeader}>
                <View style={{ flex: 1 }}>
                  <Text style={[styles.cardTitle, { color: colors.text }]}>
                    {ingredientDisplayName(item, i18n.language)}
                  </Text>
                  <Text style={{ color: colors.textMuted, marginBottom: 8 }}>
                    {categoryLabel(item.categoryCode, item.categoryName)}
                  </Text>
                </View>
                <View style={styles.cardActions}>
                  <Pressable onPress={() => openEditForm(item)}>
                    <Text style={{ color: colors.brand, fontWeight: '600' }}>{t('common.edit')}</Text>
                  </Pressable>
                  <Pressable onPress={() => deleteItem(item.id)}>
                    <Text style={{ color: '#dc2626', fontWeight: '600' }}>{t('common.delete')}</Text>
                  </Pressable>
                </View>
              </View>
              <View style={styles.macros}>
                <Macro label={t('ingredientCatalog.columns.calories')} value={`${item.caloriesPer100G}`} />
                <Macro label={t('ingredientCatalog.columns.protein')} value={formatNum(item.proteinGPer100G)} />
                <Macro label={t('ingredientCatalog.columns.fat')} value={formatNum(item.fatGPer100G)} />
                <Macro label={t('ingredientCatalog.columns.carbs')} value={formatNum(item.carbsGPer100G)} />
                {item.fiberGPer100G != null ? (
                  <Macro label={t('ingredientCatalog.columns.fiber')} value={formatNum(item.fiberGPer100G)} />
                ) : null}
              </View>
            </View>
          ))}
          <Text style={[styles.note, { color: colors.textMuted }]}>{t('ingredientCatalog.per100gNote')}</Text>
        </ScrollView>
      )}
    </Screen>
  );
}

function SortChip({ label, active, onPress }: { label: string; active: boolean; onPress: () => void }) {
  const { colors } = useAppearance();
  return (
    <Pressable
      onPress={onPress}
      style={[
        styles.sortChip,
        {
          backgroundColor: active ? colors.brand : colors.surface,
          borderColor: active ? colors.brand : colors.border,
        },
      ]}
    >
      <Text style={{ color: active ? '#fff' : colors.text, fontWeight: '600', fontSize: 12 }}>{label}</Text>
    </Pressable>
  );
}

function Chip({ label, active, onPress }: { label: string; active: boolean; onPress: () => void }) {
  const { colors } = useAppearance();
  return (
    <Pressable
      onPress={onPress}
      style={[
        styles.chip,
        {
          backgroundColor: active ? colors.brand : colors.surface,
          borderColor: active ? colors.brand : colors.border,
        },
      ]}
    >
      <Text style={{ color: active ? '#fff' : colors.text, fontWeight: '600', fontSize: 13 }}>{label}</Text>
    </Pressable>
  );
}

function Macro({ label, value }: { label: string; value: string }) {
  const { colors } = useAppearance();
  return (
    <View style={styles.macro}>
      <Text style={{ color: colors.textMuted, fontSize: 11 }}>{label}</Text>
      <Text style={{ color: colors.text, fontWeight: '600' }}>{value}</Text>
    </View>
  );
}

function formatNum(value: number): string {
  return Number(value).toFixed(1);
}

const styles = StyleSheet.create({
  chips: { gap: 8, paddingBottom: 12 },
  sortRow: { gap: 8, paddingBottom: 8 },
  sortChip: {
    borderWidth: 1,
    borderRadius: 999,
    paddingHorizontal: 12,
    paddingVertical: 6,
  },
  chip: {
    borderWidth: 1,
    borderRadius: 999,
    paddingHorizontal: 14,
    paddingVertical: 8,
  },
  formBox: { borderWidth: 1, borderRadius: 16, padding: 16, gap: 8, marginBottom: 8 },
  formTitle: { fontSize: 17, fontWeight: '700', marginBottom: 4 },
  formActions: { flexDirection: 'row', gap: 8, marginTop: 4 },
  label: { fontSize: 14, fontWeight: '600' },
  list: { gap: 12, paddingBottom: 24 },
  card: {
    borderWidth: 1,
    borderRadius: 16,
    padding: 16,
  },
  cardHeader: { flexDirection: 'row', alignItems: 'flex-start', gap: 8 },
  cardActions: { gap: 8, alignItems: 'flex-end' },
  cardTitle: { fontSize: 16, fontWeight: '700', marginBottom: 2 },
  macros: { flexDirection: 'row', flexWrap: 'wrap', gap: 12 },
  macro: { minWidth: 72 },
  note: { fontSize: 12, textAlign: 'center', marginTop: 8 },
  empty: { paddingVertical: 32, alignItems: 'center', gap: 8 },
  emptyTitle: { fontSize: 16, fontWeight: '700' },
});
