import { useEffect, useState } from 'react';
import { Box, Text, useInput } from 'ink';
import TextInput from 'ink-text-input';
import { useNavigation } from '../../state/navigation-context.js';
import { useAuth } from '../../state/auth-context.js';
import { useInventoryCounts } from '../../hooks/useInventoryCounts.js';
import { useStockNameLookup } from '../../hooks/useStockNameLookup.js';
import { LoadingSpinner } from '../shared/LoadingSpinner.js';
import { ErrorDisplay } from '../shared/ErrorDisplay.js';
import { SuccessDisplay } from '../shared/SuccessDisplay.js';
import { INVENTORY_COUNT_STATUS_LABELS } from '@effigenix/api-client';
import type { InventoryCountStatus, CountItemDTO } from '@effigenix/api-client';

type Mode = 'view' | 'menu' | 'record-item' | 'record-amount' | 'confirm-start' | 'confirm-complete' | 'cancel-reason' | 'confirm-cancel';

const STATUS_COLORS: Record<InventoryCountStatus, string> = {
  OPEN: 'yellow',
  COUNTING: 'blue',
  COMPLETED: 'green',
  CANCELLED: 'red',
};

const VISIBLE_ITEMS = 7;

export function InventoryCountDetailScreen() {
  const { params, back } = useNavigation();
  const { user } = useAuth();
  const {
    inventoryCount,
    loading,
    error,
    fetchInventoryCount,
    startInventoryCount,
    recordCountItem,
    completeInventoryCount,
    cancelInventoryCount,
    clearError,
  } = useInventoryCounts();
  const { articleName, locationName } = useStockNameLookup();

  const [mode, setMode] = useState<Mode>('view');
  const [menuIndex, setMenuIndex] = useState(0);
  const [itemIndex, setItemIndex] = useState(0);
  const [amount, setAmount] = useState('');
  const [success, setSuccess] = useState<string | null>(null);
  const [cancelReason, setCancelReason] = useState('');

  const countId = params.inventoryCountId ?? '';

  useEffect(() => {
    if (countId) void fetchInventoryCount(countId);
  }, [fetchInventoryCount, countId]);

  const items: CountItemDTO[] = inventoryCount?.countItems ?? [];
  const selectedItem = items[itemIndex];
  const countedCount = items.filter((i) => i.actualQuantityAmount !== null).length;
  const allCounted = items.length > 0 && countedCount === items.length;
  const currentUser = user?.username ?? '';
  const isDifferentUser = inventoryCount?.initiatedBy !== currentUser;

  const getMenuItems = () => {
    if (!inventoryCount) return [];
    const actions: { label: string; action: string }[] = [];
    if (inventoryCount.status === 'OPEN') {
      actions.push({ label: 'Zählung starten', action: 'start' });
      actions.push({ label: 'Inventur abbrechen', action: 'cancel' });
    }
    if (inventoryCount.status === 'COUNTING') {
      actions.push({ label: 'Position erfassen', action: 'record' });
      if (allCounted && isDifferentUser) {
        actions.push({ label: 'Inventur abschließen', action: 'complete' });
      }
      actions.push({ label: 'Inventur abbrechen', action: 'cancel' });
    }
    return actions;
  };

  const menuItems = getMenuItems();

  const handleStart = async () => {
    const result = await startInventoryCount(countId);
    if (result) {
      setSuccess('Zählung gestartet.');
      setMode('view');
    }
  };

  const handleRecordItem = async () => {
    if (!selectedItem || !amount.trim()) return;
    const result = await recordCountItem(countId, selectedItem.id, {
      actualQuantityAmount: amount.trim(),
      actualQuantityUnit: selectedItem.expectedQuantityUnit,
    });
    if (result) {
      setSuccess(`${articleName(selectedItem.articleId)} erfasst.`);
      setAmount('');
      // advance to next uncounted item or stay
      const updated = result.countItems ?? [];
      const nextUncounted = updated.findIndex((i, idx) => idx > itemIndex && i.actualQuantityAmount === null);
      if (nextUncounted >= 0) {
        setItemIndex(nextUncounted);
      }
      setMode('record-item');
    }
  };

  const handleComplete = async () => {
    const result = await completeInventoryCount(countId);
    if (result) {
      setSuccess('Inventur abgeschlossen.');
      setMode('view');
    }
  };

  const handleCancel = async () => {
    if (!cancelReason.trim()) return;
    const result = await cancelInventoryCount(countId, cancelReason.trim());
    if (result) {
      setSuccess('Inventur abgebrochen.');
      setCancelReason('');
      setMode('view');
    }
  };

  useInput((input, key) => {
    if (loading) return;

    if (mode === 'record-amount') {
      if (key.escape) setMode('record-item');
      return;
    }

    if (mode === 'cancel-reason') {
      if (key.escape) { setCancelReason(''); setMode('view'); }
      return;
    }

    if (mode === 'confirm-cancel') {
      if (input.toLowerCase() === 'j') void handleCancel();
      if (input.toLowerCase() === 'n' || key.escape) setMode('view');
      return;
    }

    if (mode === 'confirm-start') {
      if (input.toLowerCase() === 'j') void handleStart();
      if (input.toLowerCase() === 'n' || key.escape) setMode('view');
      return;
    }

    if (mode === 'confirm-complete') {
      if (input.toLowerCase() === 'j') void handleComplete();
      if (input.toLowerCase() === 'n' || key.escape) setMode('view');
      return;
    }

    if (mode === 'record-item') {
      if (key.upArrow) setItemIndex((i) => Math.max(0, i - 1));
      if (key.downArrow) setItemIndex((i) => Math.min(items.length - 1, i + 1));
      if (key.return && selectedItem) {
        setAmount(selectedItem.actualQuantityAmount ?? '');
        setMode('record-amount');
      }
      if (key.escape) setMode('view');
      return;
    }

    if (mode === 'menu') {
      if (key.upArrow) setMenuIndex((i) => Math.max(0, i - 1));
      if (key.downArrow) setMenuIndex((i) => Math.min(menuItems.length - 1, i + 1));
      if (key.return && menuItems[menuIndex]) {
        const action = menuItems[menuIndex].action;
        if (action === 'start') setMode('confirm-start');
        else if (action === 'record') { setMode('record-item'); setItemIndex(0); }
        else if (action === 'complete') setMode('confirm-complete');
        else if (action === 'cancel') { setCancelReason(''); setMode('cancel-reason'); }
      }
      if (key.escape) setMode('view');
      return;
    }

    // view mode
    if (input === 'm' && menuItems.length > 0) { setMode('menu'); setMenuIndex(0); }
    if (input === 'r') void fetchInventoryCount(countId);
    if (key.backspace || key.escape) back();
  });

  if (loading && !inventoryCount) return <LoadingSpinner label="Lade Inventur..." />;

  if (!inventoryCount) {
    return (
      <Box flexDirection="column">
        {error && <ErrorDisplay message={error} onDismiss={clearError} />}
        <Text color="red">Inventur nicht gefunden.</Text>
      </Box>
    );
  }

  const status = inventoryCount.status as InventoryCountStatus;
  const statusColor = STATUS_COLORS[status] ?? 'white';
  const statusLabel = INVENTORY_COUNT_STATUS_LABELS[status] ?? status;

  // progress bar
  const progressPct = items.length > 0 ? Math.round((countedCount / items.length) * 100) : 0;
  const barWidth = 20;
  const filled = Math.round((progressPct / 100) * barWidth);
  const progressBar = '█'.repeat(filled) + '░'.repeat(barWidth - filled);

  // scrolling window for items
  const halfWindow = Math.floor(VISIBLE_ITEMS / 2);
  let windowStart = Math.max(0, itemIndex - halfWindow);
  const windowEnd = Math.min(items.length, windowStart + VISIBLE_ITEMS);
  if (windowEnd - windowStart < VISIBLE_ITEMS && items.length >= VISIBLE_ITEMS) {
    windowStart = Math.max(0, windowEnd - VISIBLE_ITEMS);
  }
  const visibleItems = items.slice(windowStart, windowEnd);

  return (
    <Box flexDirection="column" gap={1}>
      <Box gap={2}>
        <Text color="cyan" bold>Inventur</Text>
        {loading && <Text color="gray"> (aktualisiere...)</Text>}
      </Box>

      {error && <ErrorDisplay message={error} onDismiss={clearError} />}
      {success && <SuccessDisplay message={success} onDismiss={() => setSuccess(null)} />}

      {/* Header */}
      <Box flexDirection="column" borderStyle="round" borderColor="gray" paddingX={1}>
        <Box><Text color="gray">Lagerort:       </Text><Text>{locationName(inventoryCount.storageLocationId)}</Text></Box>
        <Box><Text color="gray">Datum:          </Text><Text>{inventoryCount.countDate}</Text></Box>
        <Box><Text color="gray">Status:         </Text><Text color={statusColor} bold>{statusLabel}</Text></Box>
        <Box><Text color="gray">Erstellt von:   </Text><Text>{inventoryCount.initiatedBy}</Text></Box>
        {inventoryCount.completedBy && (
          <Box><Text color="gray">Abgeschl. von:  </Text><Text>{inventoryCount.completedBy}</Text></Box>
        )}
        {inventoryCount.cancellationReason && (
          <Box><Text color="gray">Abbruchgrund:   </Text><Text color="red">{inventoryCount.cancellationReason}</Text></Box>
        )}
        <Box>
          <Text color="gray">Fortschritt:    </Text>
          <Text color={allCounted ? 'green' : 'yellow'}>{progressBar} {countedCount}/{items.length} ({progressPct}%)</Text>
        </Box>
      </Box>

      {/* Count Items Table */}
      <Box flexDirection="column" borderStyle="round" borderColor="gray" paddingX={1}>
        <Text color="cyan" bold>Positionen ({items.length})</Text>
        {items.length === 0 ? (
          <Text color="gray" dimColor>Keine Positionen vorhanden.</Text>
        ) : (
          <>
            <Box paddingX={1}>
              <Text color="gray" bold>{'  Artikel'.padEnd(26)}</Text>
              <Text color="gray" bold>{'Soll'.padEnd(14)}</Text>
              <Text color="gray" bold>{'Ist'.padEnd(14)}</Text>
              <Text color="gray" bold>Abweichung</Text>
            </Box>
            {visibleItems.map((item, i) => {
              const actualIdx = windowStart + i;
              const isSelected = mode === 'record-item' && actualIdx === itemIndex;
              const isCounted = item.actualQuantityAmount !== null;
              const hasDeviation = isCounted && item.deviation !== null && item.deviation !== '0' && item.deviation !== '0.0';
              const rowColor = isSelected ? 'cyan' : isCounted ? (hasDeviation ? 'yellow' : 'green') : 'gray';
              const name = articleName(item.articleId);
              const expected = `${item.expectedQuantityAmount} ${item.expectedQuantityUnit}`;
              const actual = isCounted ? `${item.actualQuantityAmount} ${item.actualQuantityUnit}` : '---';
              const deviation = isCounted && item.deviation !== null ? item.deviation : '---';
              return (
                <Box key={item.id} paddingX={1}>
                  <Text color={rowColor}>{isSelected ? '▶ ' : '  '}</Text>
                  <Text color={rowColor}>{name.substring(0, 22).padEnd(23)}</Text>
                  <Text color={isSelected ? 'cyan' : 'gray'}>{expected.padEnd(14)}</Text>
                  <Text color={isSelected ? 'cyan' : (isCounted ? rowColor : 'gray')}>{actual.padEnd(14)}</Text>
                  <Text color={isSelected ? 'cyan' : (hasDeviation ? 'yellow' : 'gray')}>{deviation}</Text>
                </Box>
              );
            })}
            {items.length > VISIBLE_ITEMS && (
              <Text color="gray" dimColor>  … {items.length - VISIBLE_ITEMS} weitere Positionen (scrollen mit ↑↓)</Text>
            )}
          </>
        )}
      </Box>

      {/* Menu */}
      {mode === 'menu' && (
        <Box flexDirection="column" borderStyle="round" borderColor="cyan" paddingX={1}>
          <Text color="cyan" bold>Aktionen</Text>
          {menuItems.map((item, i) => (
            <Text key={item.action} color={i === menuIndex ? 'cyan' : 'white'}>
              {i === menuIndex ? '▶ ' : '  '}{item.label}
            </Text>
          ))}
          <Text color="gray" dimColor>↑↓ nav · Enter ausführen · Escape zurück</Text>
        </Box>
      )}

      {/* Record Item mode */}
      {mode === 'record-item' && (
        <Box flexDirection="column" borderStyle="round" borderColor="cyan" paddingX={1}>
          <Text color="cyan" bold>Position erfassen</Text>
          <Text color="gray" dimColor>↑↓ Position wählen · Enter Ist-Menge eingeben · Escape zurück</Text>
        </Box>
      )}

      {/* Record Amount */}
      {mode === 'record-amount' && selectedItem && (
        <Box flexDirection="column" borderStyle="round" borderColor="yellow" paddingX={1}>
          <Text color="yellow" bold>Ist-Menge für: {articleName(selectedItem.articleId)}</Text>
          <Text color="gray">Soll: {selectedItem.expectedQuantityAmount} {selectedItem.expectedQuantityUnit}</Text>
          <Box>
            <Text color="gray"> › </Text>
            <TextInput
              value={amount}
              onChange={setAmount}
              onSubmit={() => void handleRecordItem()}
              focus={true}
            />
            <Text color="gray"> {selectedItem.expectedQuantityUnit}</Text>
          </Box>
          <Text color="gray" dimColor>Enter bestätigen · Escape abbrechen</Text>
        </Box>
      )}

      {/* Confirm Start */}
      {mode === 'confirm-start' && (
        <Box flexDirection="column" borderStyle="round" borderColor="yellow" paddingX={1}>
          <Text color="yellow" bold>Zählung starten?</Text>
          <Text>Die Inventur wird in den Status "In Zählung" versetzt.</Text>
          <Text color="gray" dimColor>[J] Ja · [N] Nein</Text>
        </Box>
      )}

      {/* Confirm Complete */}
      {mode === 'confirm-complete' && (
        <Box flexDirection="column" borderStyle="round" borderColor="yellow" paddingX={1}>
          <Text color="yellow" bold>Inventur abschließen?</Text>
          <Text>Alle {items.length} Positionen wurden gezählt. Ausgleichsbuchungen werden erstellt.</Text>
          <Text color="gray" dimColor>[J] Ja · [N] Nein</Text>
        </Box>
      )}

      {/* Cancel Reason */}
      {mode === 'cancel-reason' && (
        <Box flexDirection="column" borderStyle="round" borderColor="red" paddingX={1}>
          <Text color="red" bold>Inventur abbrechen</Text>
          <Text color="gray">Bitte Grund eingeben:</Text>
          <Box>
            <Text color="gray"> › </Text>
            <TextInput
              value={cancelReason}
              onChange={setCancelReason}
              onSubmit={() => { if (cancelReason.trim()) setMode('confirm-cancel'); }}
              focus={true}
            />
          </Box>
          <Text color="gray" dimColor>Enter bestätigen · Escape abbrechen</Text>
        </Box>
      )}

      {/* Confirm Cancel */}
      {mode === 'confirm-cancel' && (
        <Box flexDirection="column" borderStyle="round" borderColor="red" paddingX={1}>
          <Text color="red" bold>Inventur wirklich abbrechen?</Text>
          <Text>Grund: {cancelReason}</Text>
          <Text color="gray" dimColor>[J] Ja · [N] Nein</Text>
        </Box>
      )}

      {/* Four-eyes hint */}
      {inventoryCount.status === 'COUNTING' && allCounted && !isDifferentUser && (
        <Box>
          <Text color="yellow">⚠ Vier-Augen-Prinzip: Abschluss nur durch einen anderen Benutzer möglich.</Text>
        </Box>
      )}

      <Box marginTop={1}>
        <Text color="gray" dimColor>
          {menuItems.length > 0 ? '[m] Aktionsmenü · ' : ''}[r] Refresh · Backspace Zurück
        </Text>
      </Box>
    </Box>
  );
}
