/**
 * useBarcode Hook
 *
 * Hook for barcode/QR code scanning functionality
 */

import { useState, useCallback, useRef, useEffect } from 'react';
import { BarcodeScanningResult } from 'expo-camera';
import {
  barcodeService,
  ScannedBarcode,
  ProductBarcode,
  ParsedQRData,
  BarcodeType,
  PRODUCT_BARCODE_TYPES,
  ALL_BARCODE_TYPES,
} from '@/services/barcode';

interface UseBarcodeOptions {
  // Types of barcodes to scan
  barcodeTypes?: BarcodeType[];
  // Auto-vibrate on scan
  hapticFeedback?: boolean;
  // Debounce time between scans (ms)
  scanDebounce?: number;
  // Callback when barcode is scanned
  onScan?: (barcode: ScannedBarcode) => void;
  // Callback for product barcodes
  onProductScan?: (product: ProductBarcode) => void;
  // Callback for QR codes
  onQRScan?: (data: ParsedQRData) => void;
}

interface UseBarcodeResult {
  // Permission state
  hasPermission: boolean | null;
  canAskPermission: boolean;

  // Scanner state
  isScanning: boolean;
  lastScan: ScannedBarcode | null;
  scanHistory: ScannedBarcode[];

  // Actions
  requestPermission: () => Promise<boolean>;
  handleBarcodeScan: (result: BarcodeScanningResult) => void;
  startScanning: () => void;
  stopScanning: () => void;
  clearHistory: () => void;

  // Barcode type config
  barcodeTypes: string[];
}

export function useBarcode(options: UseBarcodeOptions = {}): UseBarcodeResult {
  const {
    barcodeTypes = PRODUCT_BARCODE_TYPES,
    hapticFeedback = true,
    scanDebounce = 1000,
    onScan,
    onProductScan,
    onQRScan,
  } = options;

  // State
  const [hasPermission, setHasPermission] = useState<boolean | null>(null);
  const [canAskPermission, setCanAskPermission] = useState(true);
  const [isScanning, setIsScanning] = useState(false);
  const [lastScan, setLastScan] = useState<ScannedBarcode | null>(null);
  const [scanHistory, setScanHistory] = useState<ScannedBarcode[]>([]);

  // Refs
  const lastScanTime = useRef<number>(0);
  const lastScanData = useRef<string>('');

  // Check permission on mount
  useEffect(() => {
    barcodeService.checkPermission().then(({ granted, canAskAgain }) => {
      setHasPermission(granted);
      setCanAskPermission(canAskAgain);
    });
  }, []);

  // Request permission
  const requestPermission = useCallback(async (): Promise<boolean> => {
    const granted = await barcodeService.requestPermission();
    setHasPermission(granted);

    if (!granted) {
      const { canAskAgain } = await barcodeService.checkPermission();
      setCanAskPermission(canAskAgain);
    }

    return granted;
  }, []);

  // Handle barcode scan result
  const handleBarcodeScan = useCallback(
    async (result: BarcodeScanningResult) => {
      const now = Date.now();

      // Debounce: ignore if same barcode scanned within debounce time
      if (
        result.data === lastScanData.current &&
        now - lastScanTime.current < scanDebounce
      ) {
        return;
      }

      lastScanTime.current = now;
      lastScanData.current = result.data;

      // Convert result
      const barcode = barcodeService.convertScanResult(result);

      // Haptic feedback
      if (hapticFeedback) {
        await barcodeService.vibrate();
      }

      // Update state
      setLastScan(barcode);
      setScanHistory((prev) => [barcode, ...prev].slice(0, 20)); // Keep last 20

      // Call general callback
      onScan?.(barcode);

      // Process based on type
      if (result.type === 'qr' || result.type === 'aztec' || result.type === 'datamatrix') {
        // QR code or 2D code
        const parsed = barcodeService.parseQRData(result.data);
        onQRScan?.(parsed);
      } else {
        // Product barcode
        const parsed = barcodeService.parseProductBarcode(result.data, result.type);
        onProductScan?.(parsed);
      }
    },
    [scanDebounce, hapticFeedback, onScan, onProductScan, onQRScan]
  );

  // Start scanning
  const startScanning = useCallback(() => {
    setIsScanning(true);
    lastScanData.current = '';
    lastScanTime.current = 0;
  }, []);

  // Stop scanning
  const stopScanning = useCallback(() => {
    setIsScanning(false);
  }, []);

  // Clear scan history
  const clearHistory = useCallback(() => {
    setScanHistory([]);
    setLastScan(null);
  }, []);

  // Get barcode type strings for camera
  const barcodeTypeStrings = barcodeTypes.map((type) => type);

  return {
    // Permission state
    hasPermission,
    canAskPermission,

    // Scanner state
    isScanning,
    lastScan,
    scanHistory,

    // Actions
    requestPermission,
    handleBarcodeScan,
    startScanning,
    stopScanning,
    clearHistory,

    // Config
    barcodeTypes: barcodeTypeStrings,
  };
}

// Export presets for common use cases
export const BARCODE_PRESETS = {
  product: PRODUCT_BARCODE_TYPES,
  all: ALL_BARCODE_TYPES,
  qrOnly: ['qr'] as BarcodeType[],
  retail: ['ean13', 'ean8', 'upc_a', 'upc_e'] as BarcodeType[],
};
