/**
 * 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, useMemo } from 'react';
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 type { ValidationStepProps } from './store/types';
import type { Field, SelectOption } from '../../types';

/**
 * Create a fingerprint of the data to detect changes.
 * This is used to determine if we need to re-initialize the store
 * when navigating back to this step with potentially modified data.
 */
const createDataFingerprint = (data: Record<string, unknown>[]): string => {
  // Sample key fields that are likely to change when user modifies data in previous steps
  const keyFields = ['supplier', 'company', 'line', 'subline', 'name', 'upc', 'item_number'];

  // Create a simple hash from first few rows + last row + count
  const sampleSize = Math.min(3, data.length);
  const samples: string[] = [];

  // First few rows
  for (let i = 0; i < sampleSize; i++) {
    const row = data[i];
    const values = keyFields.map(k => String(row[k] ?? '')).join('|');
    samples.push(values);
  }

  // Last row (if different from samples)
  if (data.length > sampleSize) {
    const lastRow = data[data.length - 1];
    const values = keyFields.map(k => String(lastRow[k] ?? '')).join('|');
    samples.push(values);
  }

  return `${data.length}:${samples.join(';;')}`;
};

/**
 * Fetch field options from the API
 */
const fetchFieldOptions = async () => {
  const response = await fetch(`${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,
}: 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);
  const lastDataFingerprintRef = useRef<string | null>(null);

  // 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);

  // 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,
  });

  // Create a fingerprint of the incoming data to detect changes
  const dataFingerprint = useMemo(() => createDataFingerprint(initialData), [initialData]);

  // Initialize store with data
  useEffect(() => {
    console.log('[ValidationStep] Init effect running, initStartedRef:', initStartedRef.current, 'initPhase:', initPhase);
    console.log('[ValidationStep] Data fingerprint:', dataFingerprint, 'Last fingerprint:', lastDataFingerprintRef.current);

    // Check if data has changed since last initialization
    const dataHasChanged = lastDataFingerprintRef.current !== null && lastDataFingerprintRef.current !== dataFingerprint;

    if (dataHasChanged) {
      console.log('[ValidationStep] Data has changed - forcing re-initialization');
      // Reset all refs to allow re-initialization
      initStartedRef.current = false;
      templatesLoadedRef.current = false;
      upcValidationStartedRef.current = false;
      fieldValidationStartedRef.current = false;
    }

    // Skip if already initialized (check both ref AND store state)
    // The ref prevents double-init within the same mount cycle
    // Checking initPhase handles StrictMode remounts where store was initialized but ref persisted
    if (initStartedRef.current && initPhase !== 'idle') {
      console.log('[ValidationStep] Skipping init - already initialized');
      return;
    }

    // IMPORTANT: Skip initialization if we're returning to an already-ready store
    // with the SAME data. This happens when navigating back from ImageUploadStep.
    // We compare fingerprints to detect if the data has actually changed.
    if (initPhase === 'ready' && !dataHasChanged && lastDataFingerprintRef.current === dataFingerprint) {
      console.log('[ValidationStep] Skipping init - returning to already-ready store with same data');
      initStartedRef.current = true;
      return;
    }

    initStartedRef.current = true;
    lastDataFingerprintRef.current = dataFingerprint;

    console.log('[ValidationStep] Starting initialization with', initialData.length, 'rows');

    // Convert initialData to RowData format
    const rowData = initialData.map((row, index) => ({
      ...row,
      __index: row.__index || `row-${index}-${Date.now()}`,
    }));

    // Start with base fields
    console.log('[ValidationStep] Calling initialize()');
    initialize(rowData, BASE_IMPORT_FIELDS as unknown as Field<string>[], file);
    console.log('[ValidationStep] initialize() called');
  }, [initialData, file, initialize, initPhase, dataFingerprint]);

  // 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;
