import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import {
  ActivityIndicator,
  Modal,
  Pressable,
  RefreshControl,
  ScrollView,
  StyleSheet,
  Text,
  TextInput,
  View,
} from 'react-native';
import { router, useLocalSearchParams } from 'expo-router';
import { BarcodeScanningResult, BarcodeType, CameraView, useCameraPermissions } from 'expo-camera';

import { Customer, CustomerInventoryItem, fetchAllCustomerInventoryItems, fetchCustomers, renderPrintLabel } from '@/src/lib/api';
import { getActiveNimbotConnection, printNimbotEncodedLabel } from '@/src/lib/nimbot';
import { useAuth } from '@/src/providers/auth-provider';

const PRIMARY = '#69c350';
const SCAN_TYPES: BarcodeType[] = [
  'datamatrix',
  'code128',
  'code39',
  'code93',
  'ean13',
  'ean8',
  'upc_a',
  'upc_e',
  'itf14',
  'qr',
];

function resolveCustomerId(item: CustomerInventoryItem): number | null {
  const raw = item.customer;
  if (!raw) return null;
  if (typeof raw === 'object') {
    return raw.id ? Number(raw.id) : null;
  }
  return Number(raw);
}

function resolveCustomerName(item: CustomerInventoryItem, customersById: Map<number, Customer>): string {
  const raw = item.customer;
  if (raw && typeof raw === 'object' && raw.name) {
    return String(raw.name);
  }

  const id = resolveCustomerId(item);
  if (!id) return '-';
  return String(customersById.get(id)?.name || `#${id}`);
}

export default function InventoryScreen() {
  const { token } = useAuth();
  const params = useLocalSearchParams<{ action?: string | string[] }>();

  const [cameraPermission, requestCameraPermission] = useCameraPermissions();
  const scanTriggeredRef = useRef(false);

  const [items, setItems] = useState<CustomerInventoryItem[]>([]);
  const [customers, setCustomers] = useState<Customer[]>([]);
  const [search, setSearch] = useState('');
  const [showArchived, setShowArchived] = useState(false);
  const [loading, setLoading] = useState(true);
  const [refreshing, setRefreshing] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [printingItemId, setPrintingItemId] = useState<number | null>(null);
  const [printInfo, setPrintInfo] = useState<string | null>(null);
  const [printError, setPrintError] = useState<string | null>(null);

  const [scannerOpen, setScannerOpen] = useState(false);
  const [hasScanned, setHasScanned] = useState(false);

  const incomingAction = useMemo(() => {
    const raw = Array.isArray(params.action) ? params.action[0] : params.action;
    return String(raw || '').toLowerCase();
  }, [params.action]);

  const customersById = useMemo(() => {
    const map = new Map<number, Customer>();
    (customers || []).forEach((customer) => {
      if (Number.isFinite(Number(customer.id))) {
        map.set(Number(customer.id), customer);
      }
    });
    return map;
  }, [customers]);

  const filteredItems = useMemo(() => {
    const terms = search.trim().toLowerCase().split(/\s+/).filter(Boolean);

    return (items || [])
      .filter((item) => {
        if (!showArchived && item.archived) return false;
        if (terms.length === 0) return true;

        const customerName = resolveCustomerName(item, customersById);
        const haystack = [
          item.name,
          item.customerInventoryId,
          item.serialNumber,
          item.description,
          item.manufacturer,
          item.manufacturerNumber,
          customerName,
        ]
          .map((value) => String(value || '').toLowerCase())
          .join(' ');

        return terms.every((term) => haystack.includes(term));
      })
      .sort((a, b) => Number(b.id) - Number(a.id));
  }, [customersById, items, search, showArchived]);

  const load = useCallback(
    async (showSpinner = true) => {
      if (!token) return;
      if (showSpinner) setLoading(true);
      setError(null);

      try {
        const [inventoryRows, customerRows] = await Promise.all([
          fetchAllCustomerInventoryItems(token, true),
          fetchCustomers(token, true),
        ]);
        setItems(inventoryRows || []);
        setCustomers(customerRows || []);
      } catch (err) {
        setError(err instanceof Error ? err.message : 'Kundeninventar konnte nicht geladen werden.');
      } finally {
        setLoading(false);
        setRefreshing(false);
      }
    },
    [token]
  );

  useEffect(() => {
    if (!token) return;
    void load(true);
  }, [load, token]);

  const openScanner = useCallback(async () => {
    const granted = cameraPermission?.granted;
    if (!granted) {
      const request = await requestCameraPermission();
      if (!request.granted) {
        setError('Bitte erlaube den Zugriff auf die Kamera zum Scannen.');
        return;
      }
    }

    setHasScanned(false);
    setScannerOpen(true);
  }, [cameraPermission?.granted, requestCameraPermission]);

  useEffect(() => {
    if (incomingAction !== 'scan') return;
    if (scanTriggeredRef.current) return;
    scanTriggeredRef.current = true;
    void openScanner();
  }, [incomingAction, openScanner]);

  async function onRefresh() {
    setRefreshing(true);
    await load(false);
  }

  function closeScanner() {
    setScannerOpen(false);
    setHasScanned(false);
  }

  function onBarcodeScanned(result: BarcodeScanningResult) {
    if (hasScanned) return;
    const code = String(result.data || '').trim();
    if (!code) return;

    setHasScanned(true);
    setSearch(code);
    closeScanner();
  }

  function openNimbotForItem(item: CustomerInventoryItem, customerName: string) {
    router.push({
      pathname: '/more/nimbot',
      params: {
        itemName: item.name || '',
        itemId: item.customerInventoryId || '',
        serial: item.serialNumber || '',
        customerInventoryId: item.customerInventoryId || '',
        serialNumber: item.serialNumber || '',
        customerName,
      },
    });
  }

  async function printItemLabel(item: CustomerInventoryItem, customerName: string) {
    setPrintError(null);
    setPrintInfo(null);

    const connected = getActiveNimbotConnection();
    if (!connected) {
      openNimbotForItem(item, customerName);
      return;
    }

    if (!token) {
      setPrintError('Nicht angemeldet. Bitte erneut einloggen.');
      return;
    }

    setPrintingItemId(Number(item.id));

    try {
      const context: Record<string, unknown> = {
        id: item.id,
        customerInventoryId: item.customerInventoryId || null,
        name: item.name || null,
        customerName: customerName === '-' ? null : customerName,
        serialNumber: item.serialNumber || null,
      };

      const rendered = await renderPrintLabel(token, context, 584, 354);
      await printNimbotEncodedLabel(rendered.encoded, { density: 5, copies: 1, labelType: 1 });

      setPrintInfo(`Label gedruckt: ${item.name || item.customerInventoryId || `#${item.id}`}`);
    } catch (err) {
      setPrintError(err instanceof Error ? err.message : 'Label konnte nicht gedruckt werden.');
    } finally {
      setPrintingItemId(null);
    }
  }

  const isPrinterConnected = Boolean(getActiveNimbotConnection()?.device.id);

  return (
    <>
      <View style={styles.screen}>
        <View style={styles.searchWrap}>
          <TextInput
            placeholder="Kundeninventar suchen"
            placeholderTextColor="#9ca3af"
            style={styles.searchInput}
            value={search}
            onChangeText={setSearch}
          />
          <View style={styles.searchActions}>
            <Pressable style={styles.scanButton} onPress={openScanner}>
              <Text style={styles.scanButtonText}>Scannen</Text>
            </Pressable>
            <Pressable
              style={[styles.toggleButton, showArchived ? styles.toggleButtonActive : null]}
              onPress={() => setShowArchived((prev) => !prev)}>
              <Text style={[styles.toggleButtonText, showArchived ? styles.toggleButtonTextActive : null]}>
                Abgeschlossene anzeigen
              </Text>
            </Pressable>
          </View>
        </View>

        <ScrollView
          style={styles.list}
          contentContainerStyle={styles.listContent}
          refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />}>
          {error ? <Text style={styles.error}>{error}</Text> : null}
          {printError ? <Text style={styles.error}>{printError}</Text> : null}
          {printInfo ? <Text style={styles.info}>{printInfo}</Text> : null}

          {loading ? (
            <View style={styles.loadingBox}>
              <ActivityIndicator />
              <Text style={styles.loadingText}>Kundeninventar wird geladen...</Text>
            </View>
          ) : null}

          {!loading && filteredItems.length === 0 ? <Text style={styles.empty}>Kein Kundeninventar gefunden.</Text> : null}

          {!loading &&
            filteredItems.map((item) => {
              const customerId = resolveCustomerId(item);
              const customerName = resolveCustomerName(item, customersById);

              return (
                <Pressable
                  key={String(item.id)}
                  style={({ pressed }) => [styles.row, pressed ? styles.rowPressed : null]}
                  onPress={() => {
                    if (customerId) {
                      router.push(`/more/customer/${customerId}`);
                    }
                  }}>
                  <View style={styles.rowHeader}>
                    <Text style={styles.rowTitle} numberOfLines={1}>
                      {item.name || '-'}
                    </Text>
                    {item.archived ? <Text style={styles.badge}>Abgeschlossen</Text> : null}
                  </View>
                  <Text style={styles.rowSubtitle} numberOfLines={1}>
                    Kunde: {customerName}
                  </Text>
                  <Text style={styles.rowSubtitle} numberOfLines={1}>
                    ID: {item.customerInventoryId || '-'} · Seriennummer: {item.serialNumber || '-'}
                  </Text>
                  <View style={styles.rowActions}>
                    {(() => {
                      const isPrinting = printingItemId === Number(item.id);
                      return (
                    <Pressable
                      style={[styles.printButton, isPrinting ? styles.printButtonDisabled : null]}
                      onPress={(event) => {
                        event.stopPropagation();
                        void printItemLabel(item, customerName);
                      }}
                      disabled={isPrinting}>
                      <Text style={styles.printButtonText}>
                        {isPrinting ? 'Drucke...' : isPrinterConnected ? 'Label drucken' : 'Mit Nimbot verbinden'}
                      </Text>
                    </Pressable>
                      );
                    })()}
                  </View>
                </Pressable>
              );
            })}
        </ScrollView>
      </View>

      <Modal visible={scannerOpen} animationType="slide" onRequestClose={closeScanner}>
        <View style={styles.scannerScreen}>
          <View style={styles.scannerHeader}>
            <Text style={styles.scannerTitle}>Kundeninventar scannen</Text>
            <Pressable style={styles.scannerCloseButton} onPress={closeScanner}>
              <Text style={styles.scannerCloseButtonText}>Schließen</Text>
            </Pressable>
          </View>

          <CameraView
            style={styles.scannerCamera}
            facing="back"
            barcodeScannerSettings={{ barcodeTypes: SCAN_TYPES }}
            onBarcodeScanned={onBarcodeScanned}
          />

          <Text style={styles.scannerHint}>Barcode oder DataMatrix mittig ins Bild halten.</Text>
        </View>
      </Modal>
    </>
  );
}

const styles = StyleSheet.create({
  screen: { flex: 1, backgroundColor: '#ffffff' },
  searchWrap: {
    paddingHorizontal: 16,
    paddingTop: 12,
    paddingBottom: 10,
    borderBottomWidth: 1,
    borderBottomColor: '#e5e7eb',
    backgroundColor: '#ffffff',
    gap: 8,
  },
  searchInput: {
    borderWidth: 1,
    borderColor: '#d1d5db',
    borderRadius: 10,
    paddingHorizontal: 12,
    paddingVertical: 10,
    fontSize: 15,
    color: '#111827',
    backgroundColor: '#ffffff',
  },
  searchActions: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: 8,
    flexWrap: 'wrap',
  },
  scanButton: {
    minHeight: 36,
    borderRadius: 9,
    backgroundColor: PRIMARY,
    paddingHorizontal: 12,
    alignItems: 'center',
    justifyContent: 'center',
  },
  scanButtonText: {
    color: '#ffffff',
    fontWeight: '700',
    fontSize: 13,
  },
  toggleButton: {
    borderWidth: 1,
    borderColor: '#d1d5db',
    borderRadius: 999,
    paddingHorizontal: 10,
    paddingVertical: 6,
    backgroundColor: '#ffffff',
  },
  toggleButtonActive: {
    borderColor: PRIMARY,
    backgroundColor: '#eff9ea',
  },
  toggleButtonText: {
    color: '#374151',
    fontSize: 12,
    fontWeight: '500',
  },
  toggleButtonTextActive: {
    color: '#3d7a30',
  },
  list: { flex: 1, backgroundColor: '#ffffff' },
  listContent: { paddingBottom: 96 },
  row: {
    paddingHorizontal: 16,
    paddingVertical: 14,
    borderBottomWidth: 1,
    borderBottomColor: '#e5e7eb',
    backgroundColor: '#ffffff',
    gap: 2,
  },
  rowPressed: { backgroundColor: '#f3f4f6' },
  rowHeader: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    gap: 8,
  },
  rowTitle: {
    color: '#111827',
    fontSize: 15,
    fontWeight: '600',
    flex: 1,
    minWidth: 0,
  },
  rowSubtitle: {
    color: '#6b7280',
    fontSize: 13,
  },
  rowActions: {
    marginTop: 8,
  },
  printButton: {
    minHeight: 34,
    borderRadius: 8,
    borderWidth: 1,
    borderColor: PRIMARY,
    backgroundColor: '#eff9ea',
    paddingHorizontal: 10,
    alignItems: 'center',
    justifyContent: 'center',
    alignSelf: 'flex-start',
  },
  printButtonText: {
    color: '#3d7a30',
    fontSize: 12,
    fontWeight: '700',
  },
  badge: {
    color: '#3d7a30',
    backgroundColor: '#eff9ea',
    borderRadius: 999,
    paddingHorizontal: 8,
    paddingVertical: 4,
    fontSize: 12,
    overflow: 'hidden',
  },
  empty: {
    color: '#6b7280',
    textAlign: 'center',
    paddingVertical: 16,
  },
  loadingBox: {
    padding: 16,
    alignItems: 'center',
    gap: 8,
  },
  loadingText: {
    color: '#6b7280',
  },
  error: {
    color: '#dc2626',
    fontSize: 13,
    paddingHorizontal: 16,
    paddingTop: 10,
  },
  info: {
    color: '#166534',
    fontSize: 13,
    paddingHorizontal: 16,
    paddingTop: 10,
  },
  printButtonDisabled: {
    opacity: 0.65,
  },
  scannerScreen: {
    flex: 1,
    backgroundColor: '#000000',
  },
  scannerHeader: {
    paddingTop: 56,
    paddingHorizontal: 16,
    paddingBottom: 12,
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    gap: 10,
  },
  scannerTitle: {
    color: '#ffffff',
    fontSize: 16,
    fontWeight: '700',
    flex: 1,
    minWidth: 0,
  },
  scannerCloseButton: {
    minHeight: 34,
    borderRadius: 8,
    borderWidth: 1,
    borderColor: '#ffffff',
    paddingHorizontal: 10,
    alignItems: 'center',
    justifyContent: 'center',
  },
  scannerCloseButtonText: {
    color: '#ffffff',
    fontWeight: '600',
  },
  scannerCamera: {
    flex: 1,
  },
  scannerHint: {
    color: '#ffffff',
    fontSize: 13,
    textAlign: 'center',
    paddingHorizontal: 16,
    paddingVertical: 14,
    backgroundColor: 'rgba(17,24,39,0.85)',
  },
});
