/**
 * ValidationStep Entry Point
 *
 * The main entry component for the validation step. This component:
 * 1. Initializes the Zustand store with incoming data
 * 2. Loads field options from the API
 * 3. Orchestrates the initialization phases
 * 4. Renders the ValidationContainer once initialized
 */

import { useEffect, useRef, useDeferredValue } from 'react';
import { apiFetch } from '@/utils/api';
import { useQuery } from '@tanstack/react-query';
import { useValidationStore } from './store/validationStore';
import { useInitPhase, useIsReady } from './store/selectors';
import { ValidationContainer } from './components/ValidationContainer';
import { InitializingOverlay } from './components/InitializingOverlay';
import { useTemplateManagement } from './hooks/useTemplateManagement';
import { useUpcValidation } from './hooks/useUpcValidation';
import { useValidationActions } from './hooks/useValidationActions';
import { useProductLines } from './hooks/useProductLines';
import { useAutoInlineAiValidation } from './hooks/useAutoInlineAiValidation';
import { BASE_IMPORT_FIELDS } from '../../config';
import config from '@/config';
import { diffMappingSignatures } from './utils/mappingSignature';
import type { ValidationStepProps, RowData } from './store/types';
import type { Field, SelectOption } from '../../types';

/**
 * Fetch field options from the API
 */
const fetchFieldOptions = async () => {
  const response = await apiFetch(`${config.apiUrl}/import/field-options`);
  if (!response.ok) {
    throw new Error('Failed to fetch field options');
  }
  return response.json();
};

/**
 * Normalize option values to strings
 * API may return numeric values (e.g., supplier IDs from MySQL) but our
 * SelectOption type expects string values for consistent comparison
 */
const normalizeOptions = (options: SelectOption[]): SelectOption[] => {
  return options.map((opt) => ({
    ...opt,
    value: String(opt.value),
  }));
};

/**
 * Merge API options into base field definitions
 */
const mergeFieldOptions = (
  baseFields: typeof BASE_IMPORT_FIELDS,
  options: Record<string, SelectOption[]>
): Field<string>[] => {
  return baseFields.map((field) => {
    // Map field keys to option keys in the API response
    // Note: API returns 'sizes' and 'shippingRestrictions' not 'sizeCategories' and 'shipRestrictions'
    const optionKeyMap: Record<string, string> = {
      supplier: 'suppliers',
      company: 'companies',
      tax_cat: 'taxCategories',
      artist: 'artists',
      ship_restrictions: 'shippingRestrictions',  // API returns 'shippingRestrictions'
      size_cat: 'sizes',  // API returns 'sizes'
      categories: 'categories',
      themes: 'themes',
      colors: 'colors',
    };

    const optionKey = optionKeyMap[field.key];
    if (optionKey && options[optionKey]) {
      return {
        ...field,
        fieldType: {
          ...field.fieldType,
          // Normalize option values to strings for consistent type handling
          options: normalizeOptions(options[optionKey]),
        },
      } as Field<string>;
    }

    return field as Field<string>;
  });
};

export const ValidationStep = ({
  initialData,
  file,
  onBack,
  onNext,
  isFromScratch,
  mappingSignature,
}: ValidationStepProps) => {
  const initPhase = useInitPhase();
  const isReady = useIsReady();

  // PERFORMANCE: Defer the ready state to allow React to render heavy content
  // in the background while keeping the loading overlay visible.
  // This prevents the UI from freezing when ValidationContainer first mounts.
  const deferredIsReady = useDeferredValue(isReady);
  const isTransitioning = isReady && !deferredIsReady;

  const initStartedRef = useRef(false);
  const templatesLoadedRef = useRef(false);
  const upcValidationStartedRef = useRef(false);
  const fieldValidationStartedRef = useRef(false);

  // Debug logging
  console.log('[ValidationStep] Render - initPhase:', initPhase, 'isReady:', isReady);

  // Store actions
  const initialize = useValidationStore((state) => state.initialize);
  const setFields = useValidationStore((state) => state.setFields);
  const setFieldOptionsLoaded = useValidationStore((state) => state.setFieldOptionsLoaded);
  const setInitPhase = useValidationStore((state) => state.setInitPhase);
  const setMappingSignature = useValidationStore((state) => state.setMappingSignature);
  const reconcileMappedData = useValidationStore((state) => state.reconcileMappedData);

  // Initialization hooks
  const { loadTemplates } = useTemplateManagement();
  const { validateAllUpcs } = useUpcValidation();
  const { validateAllRows } = useValidationActions();
  const { prefetchAllLines } = useProductLines();

  // Auto inline AI validation - triggers when ready phase is reached
  useAutoInlineAiValidation();

  // Fetch field options
  const { data: fieldOptions, isLoading: optionsLoading, error: optionsError } = useQuery({
    queryKey: ['field-options'],
    queryFn: fetchFieldOptions,
    staleTime: 5 * 60 * 1000, // Cache for 5 minutes
    retry: 2,
  });

  // Initialize / reconcile store with data.
  //
  // Three cases, decided once per mount (refs are fresh because this component unmounts
  // whenever another step is shown):
  //   A. Fresh store (not yet ready)        -> full initialize() + phase chain
  //   B. Ready store, mapping unchanged      -> skip everything (preserve all edits + UPC results)
  //   C. Ready store, mapping changed        -> merge changed fields only, then re-run
  //                                             field validation (and UPC only if the
  //                                             supplier / UPC column mapping changed)
  useEffect(() => {
    if (initStartedRef.current) {
      return;
    }

    const store = useValidationStore.getState();
    const storeReady = store.initPhase === 'ready';
    const incomingSig = mappingSignature ?? null;

    // --- Case A: fresh store -> full initialization ---
    if (!storeReady) {
      initStartedRef.current = true;
      console.log('[ValidationStep] Case A - full init with', initialData.length, 'rows');

      const rowData = initialData.map((row, index) => ({
        ...row,
        __index: row.__index || `row-${index}-${store.rows.length}`,
      }));

      initialize(rowData, BASE_IMPORT_FIELDS as unknown as Field<string>[], file);
      setMappingSignature(incomingSig);
      return;
    }

    // Returning to an already-ready store.
    initStartedRef.current = true;

    // No signature (e.g. returning from ImageUpload, or restored/from-scratch flows) ->
    // nothing about the mapping could have changed; keep the store as-is.
    const diff = incomingSig
      ? diffMappingSignatures(store.mappingSignature, incomingSig)
      : null;

    // --- Case B: nothing relevant changed -> preserve everything ---
    if (!diff || diff.equal) {
      console.log('[ValidationStep] Case B - returning with unchanged mapping, preserving edits');
      return;
    }

    // --- Case C: mapping changed -> merge changed fields, re-validate selectively ---
    console.log('[ValidationStep] Case C - mapping changed', diff);
    reconcileMappedData(initialData as RowData[], diff.changedFieldKeys, diff.clearedFieldKeys);
    setMappingSignature(incomingSig);

    // Re-run the relevant phase of the validation chain. The existing phase-chain effects
    // pick these transitions up (their refs are fresh on this mount):
    //  - UPC inputs (supplier / upc column) changed -> re-run UPC + item-number, then fields
    //  - otherwise -> only re-run field validation (no UPC network calls)
    if (diff.upcAffected) {
      store.setInitialUpcValidationDone(false);
      setInitPhase('validating-upcs');
    } else {
      setInitPhase('validating-fields');
    }
  }, [
    initialData,
    file,
    initialize,
    reconcileMappedData,
    setMappingSignature,
    setInitPhase,
    mappingSignature,
  ]);

  // Update fields when options are loaded
  // CRITICAL: Check store state (not ref) because initialize() resets the store
  // In StrictMode, effects double-run. If we used a ref:
  //   1. First pass: merge runs, ref = true, phase advances
  //   2. Second pass: initialize() resets store (phase back to loading-options), but ref is still true, so merge SKIPS
  //   3. Phase stuck at loading-options!
  // By checking fieldOptionsLoaded from store, we re-run merge after store reset.
  useEffect(() => {
    const { fieldOptionsLoaded } = useValidationStore.getState();
    console.log('[ValidationStep] Field options effect - fieldOptions:', !!fieldOptions, 'initPhase:', initPhase, 'fieldOptionsLoaded:', fieldOptionsLoaded);

    // Skip if no options or already loaded in store
    if (!fieldOptions || fieldOptionsLoaded) return;

    console.log('[ValidationStep] Merging field options');
    const mergedFields = mergeFieldOptions(BASE_IMPORT_FIELDS, fieldOptions);
    setFields(mergedFields);
    setFieldOptionsLoaded(true);

    // Move to next phase - use current store state to avoid race condition
    // The initPhase variable may be stale if initialization ran in the same cycle
    // CRITICAL: Also handle 'idle' phase for when React Query returns cached data
    // before the initialization effect has a chance to run
    const currentPhase = useValidationStore.getState().initPhase;
    console.log('[ValidationStep] Checking phase transition - currentPhase:', currentPhase);
    if (currentPhase === 'loading-options' || currentPhase === 'idle') {
      console.log('[ValidationStep] Transitioning to loading-templates');
      setInitPhase('loading-templates');
    }
  }, [fieldOptions, initPhase, setFields, setFieldOptionsLoaded, setInitPhase]);

  // Note: We intentionally do NOT reset the store on unmount.
  // React StrictMode double-mounts components, and resetting on unmount
  // causes the store to be cleared before the second mount, while refs
  // persist, causing initialization to be skipped.
  // The store will be reset when initialize() is called on the next import.

  // Load templates when entering loading-templates phase
  useEffect(() => {
    if (initPhase === 'loading-templates' && !templatesLoadedRef.current) {
      templatesLoadedRef.current = true;
      loadTemplates().then(() => {
        setInitPhase('validating-upcs');
      });
    }
  }, [initPhase, loadTemplates, setInitPhase]);

  // Run UPC validation when entering validating-upcs phase
  useEffect(() => {
    if (initPhase === 'validating-upcs' && !upcValidationStartedRef.current) {
      upcValidationStartedRef.current = true;
      validateAllUpcs();
    }
  }, [initPhase, validateAllUpcs]);

  // Run field validation when entering validating-fields phase
  useEffect(() => {
    if (initPhase === 'validating-fields' && !fieldValidationStartedRef.current) {
      fieldValidationStartedRef.current = true;

      // Run field validation (includes unique validation in batch) and prefetch lines
      // NOTE: validateAllRows now handles unique field validation in its batch,
      // so we don't call validateUniqueFields() separately here.
      Promise.all([
        validateAllRows(),
        prefetchAllLines(),
      ]).then(() => {
        setInitPhase('ready');
      });
    }
  }, [initPhase, validateAllRows, prefetchAllLines, setInitPhase]);

  // Show error state if options failed to load
  if (optionsError) {
    return (
      <div className="flex flex-col items-center justify-center h-[calc(100vh-9.5rem)] gap-4">
        <div className="text-destructive text-lg">Failed to load field options</div>
        <div className="text-muted-foreground text-sm">
          {optionsError instanceof Error ? optionsError.message : 'Unknown error'}
        </div>
        {onBack && (
          <button
            onClick={onBack}
            className="px-4 py-2 text-sm bg-secondary text-secondary-foreground rounded-md hover:bg-secondary/80"
          >
            Go Back
          </button>
        )}
      </div>
    );
  }

  // Show loading overlay while initializing
  // Use deferredIsReady to keep showing loading state while React processes
  // the heavy ValidationContainer in the background
  if (!deferredIsReady || optionsLoading) {
    return (
      <InitializingOverlay
        phase={initPhase}
        message={
          optionsLoading
            ? 'Loading field options...'
            : isTransitioning
              ? 'Preparing table...'
              : undefined
        }
      />
    );
  }

  return (
    <ValidationContainer
      onBack={onBack}
      onNext={onNext}
      isFromScratch={isFromScratch}
    />
  );
};

export default ValidationStep;
