/**
 * useUpcValidation Hook
 *
 * Handles UPC validation and item number generation.
 * Validates UPCs against the API and caches results for efficiency.
 *
 * PERFORMANCE NOTE: This hook must NOT subscribe to the rows array!
 * Subscribing to rows causes re-render on EVERY cell change.
 * Uses getState() to read rows at action time instead.
 */

import { useCallback, useRef } from 'react';
import { apiFetch } from '@/utils/api';
import { useValidationStore } from '../store/validationStore';
import { useInitialUpcValidationDone } from '../store/selectors';
import { ErrorSource, ErrorType, type UpcValidationResult } from '../store/types';
import { correctUpcValue } from '../utils/upcUtils';
import config from '@/config';

const BATCH_SIZE = 50;
const BATCH_DELAY = 100; // ms between batches

/**
 * Fetch product by UPC from API
 */
const fetchProductByUpc = async (
  supplierId: string,
  upcValue: string
): Promise<UpcValidationResult> => {
  try {
    const response = await apiFetch(
      `${config.apiUrl}/import/check-upc-and-generate-sku?upc=${encodeURIComponent(upcValue)}&supplierId=${encodeURIComponent(supplierId)}`
    );

    let payload: Record<string, unknown> | null = null;
    try {
      payload = await response.json();
    } catch {
      // Non-JSON responses handled below
    }

    if (response.status === 409) {
      return {
        success: false,
        error: (payload?.error as string) || 'UPC already exists',
        code: 'conflict',
      };
    }

    if (!response.ok) {
      return {
        success: false,
        error: (payload?.error as string) || `API error (${response.status})`,
        code: 'http_error',
      };
    }

    if (!payload?.success) {
      return {
        success: false,
        error: (payload?.message as string) || 'Unknown error',
        code: 'invalid_response',
      };
    }

    return {
      success: true,
      itemNumber: (payload.itemNumber as string) || '',
    };
  } catch (error) {
    console.error('Network error validating UPC:', error);
    return {
      success: false,
      error: 'Network error',
      code: 'network_error',
    };
  }
};

/**
 * Hook for UPC validation operations
 * PERFORMANCE: Does NOT subscribe to rows - uses getState() at action time
 */
export const useUpcValidation = () => {
  // PERFORMANCE: Only subscribe to initialValidationDone, NOT rows
  const initialValidationDone = useInitialUpcValidationDone();

  // Store actions (these are stable from Zustand)
  const setUpcStatus = useValidationStore((state) => state.setUpcStatus);
  const setGeneratedItemNumber = useValidationStore((state) => state.setGeneratedItemNumber);
  const cacheUpcResult = useValidationStore((state) => state.cacheUpcResult);
  const getCachedItemNumber = useValidationStore((state) => state.getCachedItemNumber);
  const setInitialUpcValidationDone = useValidationStore((state) => state.setInitialUpcValidationDone);
  const updateCell = useValidationStore((state) => state.updateCell);
  const setError = useValidationStore((state) => state.setError);
  const clearFieldError = useValidationStore((state) => state.clearFieldError);
  const startValidatingCell = useValidationStore((state) => state.startValidatingCell);
  const stopValidatingCell = useValidationStore((state) => state.stopValidatingCell);
  const setInitPhase = useValidationStore((state) => state.setInitPhase);

  // Track active validations to prevent duplicates
  const activeValidationsRef = useRef(new Set<string>());
  const initialValidationStartedRef = useRef(false);

  /**
   * Validate a single UPC for a row
   * IMPORTANT: This callback is stable due to only using store actions as deps
   */
  const validateUpc = useCallback(
    async (rowIndex: number, supplierId: string, upcValue: string) => {
      const validationKey = `${rowIndex}-${supplierId}-${upcValue}`;

      // Cancel any previous validation for this row
      const prevKeys = Array.from(activeValidationsRef.current).filter((k) =>
        k.startsWith(`${rowIndex}-`)
      );
      prevKeys.forEach((k) => activeValidationsRef.current.delete(k));

      activeValidationsRef.current.add(validationKey);

      // Set loading state
      setUpcStatus(rowIndex, 'validating');
      startValidatingCell(rowIndex, 'item_number');

      try {
        // Check cache first
        const cached = getCachedItemNumber(supplierId, upcValue);
        if (cached) {
          setGeneratedItemNumber(rowIndex, cached);
          clearFieldError(rowIndex, 'upc');
          setUpcStatus(rowIndex, 'done');
          return { success: true, itemNumber: cached };
        }

        // Make API call
        const result = await fetchProductByUpc(supplierId, upcValue);

        // Check if this validation is still relevant
        if (!activeValidationsRef.current.has(validationKey)) {
          return { success: false };
        }

        if (result.success && result.itemNumber) {
          // Cache and apply result
          cacheUpcResult(supplierId, upcValue, result.itemNumber);
          setGeneratedItemNumber(rowIndex, result.itemNumber);
          clearFieldError(rowIndex, 'upc');
          setUpcStatus(rowIndex, 'done');
          return result;
        } else {
          // Clear item number on error
          updateCell(rowIndex, 'item_number', '');
          setUpcStatus(rowIndex, 'error');

          // Set specific error for conflicts
          if (result.code === 'conflict') {
            setError(rowIndex, 'upc', {
              message: 'A product with this UPC already exists',
              level: 'error',
              source: ErrorSource.Upc,
              type: ErrorType.Unique,
            });
          }

          return result;
        }
      } catch (error) {
        console.error('Error validating UPC:', error);
        setUpcStatus(rowIndex, 'error');
        return { success: false, error: 'Validation error' };
      } finally {
        stopValidatingCell(rowIndex, 'item_number');
        activeValidationsRef.current.delete(validationKey);
      }
    },
    [
      getCachedItemNumber,
      setUpcStatus,
      setGeneratedItemNumber,
      cacheUpcResult,
      updateCell,
      setError,
      clearFieldError,
      startValidatingCell,
      stopValidatingCell,
    ]
  );

  /**
   * Validate all UPCs in batch during initialization
   * PERFORMANCE: Uses getState() to read rows at action time
   */
  const validateAllUpcs = useCallback(async () => {
    if (initialValidationStartedRef.current) return;
    initialValidationStartedRef.current = true;

    // Get current rows at action time via getState()
    const currentRows = useValidationStore.getState().rows;

    console.log('[UPC Validation] Starting batch validation for', currentRows.length, 'rows');

    // Find rows that need UPC validation
    const rowsToValidate = currentRows
      .map((row, index) => ({ row, index }))
      .filter(({ row }) => row.supplier && (row.upc || row.barcode));

    console.log('[UPC Validation] Found', rowsToValidate.length, 'rows with supplier and UPC/barcode');

    if (rowsToValidate.length === 0) {
      console.log('[UPC Validation] No rows to validate, skipping to next phase');
      setInitialUpcValidationDone(true);
      setInitPhase('validating-fields');
      return;
    }

    // Process in batches
    for (let i = 0; i < rowsToValidate.length; i += BATCH_SIZE) {
      const batch = rowsToValidate.slice(i, i + BATCH_SIZE);

      // Process batch in parallel
      await Promise.all(
        batch.map(async ({ row, index }) => {
          const supplierId = String(row.supplier);
          const rawUpc = String(row.upc || row.barcode);

          // Apply UPC check digit correction before validating
          // This handles imported data with incorrect/missing check digits
          const { corrected: upcValue, changed: upcCorrected } = correctUpcValue(rawUpc);

          // If UPC was corrected, update the cell value
          if (upcCorrected) {
            updateCell(index, 'upc', upcValue);
          }

          // Mark as validating
          setUpcStatus(index, 'validating');
          startValidatingCell(index, 'item_number');

          try {
            // Check cache first
            const cached = getCachedItemNumber(supplierId, upcValue);
            if (cached) {
              setGeneratedItemNumber(index, cached);
              setUpcStatus(index, 'done');
              return;
            }

            // Make API call
            const result = await fetchProductByUpc(supplierId, upcValue);

            console.log(`[UPC Validation] Row ${index}: supplierId=${supplierId}, upc=${upcValue}, result=`, result);

            if (result.success && result.itemNumber) {
              console.log(`[UPC Validation] Row ${index}: Setting item_number to "${result.itemNumber}"`);
              cacheUpcResult(supplierId, upcValue, result.itemNumber);
              setGeneratedItemNumber(index, result.itemNumber);
              clearFieldError(index, 'upc');
              setUpcStatus(index, 'done');
            } else {
              console.log(`[UPC Validation] Row ${index}: No item number returned, error code=${result.code}`);
              updateCell(index, 'item_number', '');
              setUpcStatus(index, 'error');

              if (result.code === 'conflict') {
                setError(index, 'upc', {
                  message: 'A product with this UPC already exists',
                  level: 'error',
                  source: ErrorSource.Upc,
                  type: ErrorType.Unique,
                });
              }
            }
          } catch (error) {
            console.error(`Error validating UPC for row ${index}:`, error);
            setUpcStatus(index, 'error');
          } finally {
            stopValidatingCell(index, 'item_number');
          }
        })
      );

      // Small delay between batches for UI responsiveness
      if (i + BATCH_SIZE < rowsToValidate.length) {
        await new Promise((resolve) => setTimeout(resolve, BATCH_DELAY));
      }
    }

    setInitialUpcValidationDone(true);
    setInitPhase('validating-fields');
  }, [
    // Only stable store actions as dependencies
    getCachedItemNumber,
    setUpcStatus,
    setGeneratedItemNumber,
    cacheUpcResult,
    updateCell,
    setError,
    clearFieldError,
    startValidatingCell,
    stopValidatingCell,
    setInitialUpcValidationDone,
    setInitPhase,
  ]);

  return {
    validateUpc,
    validateAllUpcs,
    initialValidationDone,
  };
};
