import { useState, useEffect, useMemo, useCallback } from 'react';
import { Box, Text, useInput } from 'ink';
import { useNavigation } from '../../state/navigation-context.js';
import { useBatches } from '../../hooks/useBatches.js';
import { FormInput } from '../shared/FormInput.js';
import { LoadingSpinner } from '../shared/LoadingSpinner.js';
import { ErrorDisplay } from '../shared/ErrorDisplay.js';
import { UOM_VALUES, UOM_LABELS } from '@effigenix/api-client';
import type { UoM, RecipeDTO, ArticleDTO, StockBatchDTO, IngredientDTO } from '@effigenix/api-client';
import { client } from '../../utils/api-client.js';

type Phase = 'loading' | 'pick-ingredient' | 'pick-batch' | 'edit-quantity' | 'submitting' | 'success' | 'error';

interface AvailableBatch {
  stockBatch: StockBatchDTO;
  stockId: string;
}

export function RecordConsumptionScreen() {
  const { params, back } = useNavigation();
  const { recordConsumption, error: submitError, clearError } = useBatches();

  const batchId = params.batchId ?? '';

  // Data state
  const [recipe, setRecipe] = useState<RecipeDTO | null>(null);
  const [articles, setArticles] = useState<ArticleDTO[]>([]);
  const [consumedArticleIds, setConsumedArticleIds] = useState<Set<string>>(new Set());
  const [plannedQuantity, setPlannedQuantity] = useState<number>(0);

  // Selection state
  const [phase, setPhase] = useState<Phase>('loading');
  const [ingredientCursor, setIngredientCursor] = useState(0);
  const [selectedIngredient, setSelectedIngredient] = useState<IngredientDTO | null>(null);
  const [availableBatches, setAvailableBatches] = useState<AvailableBatch[]>([]);
  const [batchCursor, setBatchCursor] = useState(0);
  const [selectedBatch, setSelectedBatch] = useState<AvailableBatch | null>(null);

  // Quantity edit state
  const [quantityValue, setQuantityValue] = useState('');
  const [uomIdx, setUomIdx] = useState(0);
  const [loadError, setLoadError] = useState<string | null>(null);

  const articleName = useCallback((id: string) => {
    const a = articles.find((art) => art.id === id);
    return a ? `${a.articleNumber} – ${a.name}` : id.substring(0, 18);
  }, [articles]);

  // Load batch, recipe, articles on mount
  useEffect(() => {
    async function load() {
      try {
        const [batchData, articleList] = await Promise.all([
          client.batches.getById(batchId),
          client.articles.list(),
        ]);
        setArticles(articleList);
        setPlannedQuantity(parseFloat(batchData.plannedQuantity ?? '0'));

        // Track already consumed articles
        const consumed = new Set((batchData.consumptions ?? []).map((c) => c.articleId ?? ''));
        setConsumedArticleIds(consumed);

        if (!batchData.recipeId) {
          setLoadError('Charge hat keine Rezept-ID.');
          setPhase('error');
          return;
        }

        const recipeData = await client.recipes.getById(batchData.recipeId);
        setRecipe(recipeData);
        setPhase('pick-ingredient');
      } catch (err) {
        setLoadError(err instanceof Error ? err.message : 'Fehler beim Laden');
        setPhase('error');
      }
    }
    void load();
  }, [batchId]);

  // Calculate scaled quantity for an ingredient
  const scaledQuantity = useCallback((ingredient: IngredientDTO): string => {
    if (!recipe) return ingredient.quantity;
    const recipeOutput = parseFloat(recipe.outputQuantity);
    if (!recipeOutput || recipeOutput === 0) return ingredient.quantity;
    const ingredientQty = parseFloat(ingredient.quantity);
    const scale = plannedQuantity / recipeOutput;
    return (ingredientQty * scale).toFixed(2).replace(/\.?0+$/, '');
  }, [recipe, plannedQuantity]);

  // Ingredients sorted by position
  const sortedIngredients = useMemo(() => {
    if (!recipe) return [];
    return [...recipe.ingredients].sort((a, b) => a.position - b.position);
  }, [recipe]);

  // Load available batches for selected ingredient's article
  const loadBatchesForArticle = useCallback(async (articleId: string) => {
    try {
      const stocks = await client.stocks.list({ articleId });
      const batches: AvailableBatch[] = [];
      for (const stock of stocks) {
        for (const sb of stock.batches) {
          if (sb.status === 'AVAILABLE' || sb.status === 'EXPIRING_SOON') {
            batches.push({ stockBatch: sb, stockId: stock.id });
          }
        }
      }
      setAvailableBatches(batches);
      setBatchCursor(0);
    } catch {
      setAvailableBatches([]);
    }
  }, []);

  // Handle input based on current phase
  useInput((_input, key) => {
    if (phase === 'loading' || phase === 'submitting' || phase === 'success') return;

    if (key.escape) {
      if (phase === 'edit-quantity') {
        setPhase('pick-batch');
        return;
      }
      if (phase === 'pick-batch') {
        setPhase('pick-ingredient');
        return;
      }
      back();
      return;
    }

    if (phase === 'pick-ingredient') {
      if (key.upArrow) setIngredientCursor((c) => Math.max(0, c - 1));
      if (key.downArrow) setIngredientCursor((c) => Math.min(sortedIngredients.length - 1, c + 1));
      if (key.return && sortedIngredients[ingredientCursor]) {
        const ing = sortedIngredients[ingredientCursor]!;
        setSelectedIngredient(ing);
        void loadBatchesForArticle(ing.articleId);
        setPhase('pick-batch');
      }
      return;
    }

    if (phase === 'pick-batch') {
      if (key.upArrow) setBatchCursor((c) => Math.max(0, c - 1));
      if (key.downArrow) setBatchCursor((c) => Math.min(availableBatches.length - 1, c + 1));
      if (key.return && availableBatches[batchCursor]) {
        const batch = availableBatches[batchCursor]!;
        setSelectedBatch(batch);
        // Pre-fill quantity from recipe (scaled)
        if (selectedIngredient) {
          setQuantityValue(scaledQuantity(selectedIngredient));
          const uomIndex = UOM_VALUES.indexOf(selectedIngredient.uom as UoM);
          setUomIdx(uomIndex >= 0 ? uomIndex : 0);
        }
        setPhase('edit-quantity');
      }
      return;
    }

    if (phase === 'edit-quantity') {
      if (key.leftArrow || key.rightArrow) {
        const dir = key.rightArrow ? 1 : -1;
        setUomIdx((i) => (i + dir + UOM_VALUES.length) % UOM_VALUES.length);
      }
    }
  });

  const handleSubmit = async () => {
    if (!selectedIngredient || !selectedBatch || !quantityValue.trim()) return;
    setPhase('submitting');
    const result = await recordConsumption(batchId, {
      inputBatchId: selectedBatch.stockBatch.batchId ?? '',
      articleId: selectedIngredient.articleId,
      quantityUsed: quantityValue.trim(),
      quantityUnit: UOM_VALUES[uomIdx] as string,
    });
    if (result) {
      setPhase('success');
      setTimeout(() => back(), 1500);
    } else {
      setPhase('edit-quantity');
    }
  };

  // ── Render ──

  if (phase === 'loading') return <LoadingSpinner label="Lade Rezeptdaten..." />;
  if (phase === 'submitting') return <LoadingSpinner label="Verbrauch wird erfasst..." />;

  if (phase === 'error') {
    return (
      <Box flexDirection="column" paddingY={1}>
        <ErrorDisplay message={loadError ?? 'Unbekannter Fehler'} onDismiss={() => back()} />
      </Box>
    );
  }

  if (phase === 'success') {
    return (
      <Box flexDirection="column" paddingY={1}>
        <Text color="green" bold>Verbrauch erfolgreich erfasst.</Text>
      </Box>
    );
  }

  const uomLabel = (u: string) => UOM_LABELS[u as UoM] ?? u;

  // ── Phase: Pick Ingredient ──
  if (phase === 'pick-ingredient') {
    return (
      <Box flexDirection="column" gap={1}>
        <Text color="cyan" bold>Verbrauch erfassen – Zutat wählen</Text>
        {submitError && <ErrorDisplay message={submitError} onDismiss={clearError} />}

        <Box flexDirection="column" borderStyle="round" borderColor="gray" paddingX={1}>
          {sortedIngredients.map((ing, i) => {
            const consumed = consumedArticleIds.has(ing.articleId);
            const scaled = scaledQuantity(ing);
            const color = consumed ? 'gray' : (i === ingredientCursor ? 'cyan' : 'white');
            return (
              <Box key={ing.id}>
                <Text color={color}>
                  {i === ingredientCursor ? '▶ ' : '  '}
                  {`${ing.position}. `.padEnd(4)}
                  {articleName(ing.articleId).padEnd(35)}
                  {`${scaled} ${uomLabel(ing.uom)}`.padEnd(20)}
                  {consumed ? '✓ erfasst' : ''}
                </Text>
              </Box>
            );
          })}
        </Box>

        <Text color="gray" dimColor>↑↓ wählen · Enter auswählen · Escape zurück</Text>
      </Box>
    );
  }

  // ── Phase: Pick Batch ──
  if (phase === 'pick-batch' && selectedIngredient) {
    return (
      <Box flexDirection="column" gap={1}>
        <Text color="cyan" bold>Verbrauch erfassen – Input-Charge wählen</Text>
        <Text color="gray">Zutat: {articleName(selectedIngredient.articleId)} · Soll: {scaledQuantity(selectedIngredient)} {uomLabel(selectedIngredient.uom)}</Text>

        {availableBatches.length === 0 ? (
          <Box paddingY={1}>
            <Text color="yellow">Keine verfügbaren Chargen für diesen Artikel.</Text>
          </Box>
        ) : (
          <Box flexDirection="column" borderStyle="round" borderColor="gray" paddingX={1}>
            <Box>
              <Text color="gray" bold>{'  Chargen-ID'.padEnd(24)}{'Menge'.padEnd(18)}{'MHD'.padEnd(14)}Status</Text>
            </Box>
            {availableBatches.map((ab, i) => {
              const sb = ab.stockBatch;
              const color = i === batchCursor ? 'cyan' : 'white';
              return (
                <Box key={`${ab.stockId}-${sb.id}`}>
                  <Text color={color}>
                    {i === batchCursor ? '▶ ' : '  '}
                    {(sb.batchId ?? '').padEnd(22)}
                    {`${sb.quantityAmount ?? ''} ${uomLabel(sb.quantityUnit ?? '')}`.padEnd(18)}
                    {(sb.expiryDate ?? '').padEnd(14)}
                    {sb.status ?? ''}
                  </Text>
                </Box>
              );
            })}
          </Box>
        )}

        <Text color="gray" dimColor>↑↓ wählen · Enter auswählen · Escape zurück</Text>
      </Box>
    );
  }

  // ── Phase: Edit Quantity ──
  if (phase === 'edit-quantity' && selectedIngredient && selectedBatch) {
    const currentUomLabel = UOM_LABELS[UOM_VALUES[uomIdx] as UoM] ?? UOM_VALUES[uomIdx];
    return (
      <Box flexDirection="column" gap={1}>
        <Text color="cyan" bold>Verbrauch erfassen – Menge bestätigen</Text>
        <Text color="gray">Zutat: {articleName(selectedIngredient.articleId)}</Text>
        <Text color="gray">Charge: {selectedBatch.stockBatch.batchId} ({selectedBatch.stockBatch.quantityAmount} {uomLabel(selectedBatch.stockBatch.quantityUnit ?? '')} verfügbar)</Text>
        {submitError && <ErrorDisplay message={submitError} onDismiss={clearError} />}

        <Box flexDirection="column" gap={1} width={60}>
          <FormInput
            label="Verbrauchte Menge *"
            value={quantityValue}
            onChange={setQuantityValue}
            onSubmit={() => void handleSubmit()}
            focus={true}
          />
          <Box flexDirection="column">
            <Text color="cyan">
              Mengeneinheit * (←→ wechseln): <Text bold color="white">{`< ${currentUomLabel} >`}</Text>
            </Text>
          </Box>
        </Box>

        <Text color="gray" dimColor>←→ Einheit · Enter speichern · Escape zurück</Text>
      </Box>
    );
  }

  return null;
}
