import React, { useState, useEffect, useCallback, useMemo } from 'react'
import { useValidationState } from '../hooks/useValidationState'
import { Props, RowData } from '../hooks/validationTypes'
import { Button } from '@/components/ui/button'
import { Loader2, X, Plus, Edit3, Sparkles, FileText } from 'lucide-react'
import { toast } from 'sonner'
import { Switch } from '@/components/ui/switch'
import { useRsi } from '../../../hooks/useRsi'
import SearchableTemplateSelect from './SearchableTemplateSelect'
import { useAiValidation } from '../hooks/useAiValidation'
import { AiValidationDialogs } from './AiValidationDialogs'
import { Fields } from '../../../types'
import { SearchProductTemplateDialog } from '@/components/templates/SearchProductTemplateDialog'
import { TemplateForm } from '@/components/templates/TemplateForm'
import { CreateProductCategoryDialog, type CreatedCategoryInfo } from '@/components/product-import/CreateProductCategoryDialog'
import axios from 'axios'
import { RowSelectionState } from '@tanstack/react-table'
import { useProductLinesFetching } from '../hooks/useProductLinesFetching'
import UpcValidationTableAdapter from './UpcValidationTableAdapter'
import { Skeleton } from '@/components/ui/skeleton'
import { Protected } from '@/components/auth/Protected'
import { normalizeCountryCode } from '../utils/countryUtils'
import { cleanPriceField } from '../utils/priceUtils'
import { correctUpcValue } from '../utils/upcUtils'
import InitializingValidation from './InitializingValidation'
/**
 * ValidationContainer component - the main wrapper for the validation step
 * 
 * This component is responsible for:
 * - Managing global state using hooks
 * - Coordinating between subcomponents
 * - Handling navigation events (next, back)
 */
const ValidationContainer = <T extends string>({ 
  initialData,
  file,
  onBack,
  onNext,
  isFromScratch
}: Props<T>) => {
  // Use our main validation state hook
  const validationState = useValidationState<T>({
    initialData,
    file,
    onBack,
    onNext,
    isFromScratch
  })

  const {
    data,
    filteredData,
    validationErrors,
    rowSelection,
    setRowSelection,
    templates,
    selectedTemplateId,
    applyTemplate,
    applyTemplateToSelected,
    getTemplateDisplayText,
    filters,
    updateFilters,
    loadTemplates,
    setData,
    fields,
    upcValidation,
    isLoadingTemplates,
    isInitializing,
    initializationTasks,
    validatingCells,
    setValidatingCells,
    editingCells,
    setEditingCells,
    updateRow,
    revalidateRows
  } = validationState

  const dataIndexByRowId = useMemo(() => {
    const map = new Map<any, number>()
    data.forEach((row, index) => {
      const rowId = (row as Record<string, any>).__index
      if (rowId !== undefined && rowId !== null) {
        map.set(rowId, index)
      }
    })
    return map
  }, [data])
  
  // Use product lines fetching hook
  const {
    rowProductLines,
    rowSublines,
    isLoadingLines,
    isLoadingSublines,
    fetchProductLines,
    fetchSublines
  } = useProductLinesFetching(data);
  const handleValidationCategoryCreated = useCallback(
    async ({ type, parentId }: CreatedCategoryInfo) => {
      try {
        if (type === "line") {
          await fetchProductLines(null, parentId);
        } else {
          await fetchSublines(null, parentId);
        }
      } catch (error) {
        console.error("Failed to refresh product categories:", error);
      }
    },
    [fetchProductLines, fetchSublines],
  );
  
  // Function to check if a specific row is being validated - memoized
  const isRowValidatingUpc = upcValidation.isRowValidatingUpc;
  
  // Apply all pending updates to the data state
  
  // Use AI validation hook
  const aiValidation = useAiValidation<T>(
    data,
    setData,
    fields as Fields<T>,
    // Create a wrapper function that adapts the rowHook to the expected signature
    validationState.rowHook ?
      async (row) => {
        // Call the original rowHook and return the row itself instead of just Meta
        await validationState.rowHook(row, 0, data);
        return row;
      } :
      undefined,
    // Create a wrapper function that adapts the tableHook to the expected signature
    validationState.tableHook ?
      async (rows) => {
        // Call the original tableHook and return the rows themselves
        await validationState.tableHook(rows);
        return rows;
      } :
      undefined,
    revalidateRows // Pass revalidateRows for post-AI validation
  );
  
  const { translations } = useRsi<T>()

  // State for product search dialog
  const [isProductSearchDialogOpen, setIsProductSearchDialogOpen] = useState(false)

  // Add new state for template form dialog
  const [isTemplateFormOpen, setIsTemplateFormOpen] = useState(false)
  const [templateFormInitialData, setTemplateFormInitialData] = useState<any>(null)

  const [fieldOptions, setFieldOptions] = useState<any>(null)

  const selectedRowCategoryDefaults = useMemo(() => {
    const selectedEntries = Object.entries(rowSelection).filter(([, selected]) => selected);

    const resolveRowByKey = (key: string): Record<string, any> | undefined => {
      const numericIndex = Number(key);
      if (!Number.isNaN(numericIndex) && numericIndex >= 0 && numericIndex < filteredData.length) {
        return filteredData[numericIndex] as Record<string, any>;
      }

      return data.find((row) => {
        if (row.__index === undefined || row.__index === null) {
          return false;
        }
        return String(row.__index) === key;
      }) as Record<string, any> | undefined;
    };

    const targetRows: Record<string, any>[] = selectedEntries.length
      ? selectedEntries
          .map(([key]) => resolveRowByKey(key))
          .filter((row): row is Record<string, any> => Boolean(row))
      : (filteredData.length ? filteredData : data) as Record<string, any>[];

    if (!targetRows.length) {
      return { company: undefined as string | undefined, line: undefined as string | undefined };
    }

    const uniqueCompanyValues = new Set<string>();
    const uniqueLineValues = new Set<string>();

    targetRows.forEach((row) => {
      const companyValue = row.company;
      if (companyValue !== undefined && companyValue !== null && String(companyValue).trim() !== "") {
        uniqueCompanyValues.add(String(companyValue));
      }

      const lineValue = row.line;
      if (lineValue !== undefined && lineValue !== null && String(lineValue).trim() !== "") {
        uniqueLineValues.add(String(lineValue));
      }
    });

    const resolvedCompany = uniqueCompanyValues.size === 1 ? Array.from(uniqueCompanyValues)[0] : undefined;
    const resolvedLine = uniqueLineValues.size === 1 ? Array.from(uniqueLineValues)[0] : undefined;

    return {
      company: resolvedCompany,
      line: resolvedLine,
    };
  }, [rowSelection, filteredData, data]);

  // Track fields that need revalidation due to value changes
  // Combined state: Map<rowIndex, fieldKeys[]> - if empty array, revalidate all fields
  const [fieldsToRevalidate, setFieldsToRevalidate] = useState<Map<number, string[]>>(new Map());

  // Function to mark a row for revalidation
  const markRowForRevalidation = useCallback((rowIndex: number, fieldKey?: string) => {
    // Map filtered rowIndex to original data index via __index
    const originalIndex = (() => {
      try {
        const row = filteredData[rowIndex];
        if (!row) return rowIndex;
        const id = row.__index;
        if (!id) return rowIndex;
        const idx = data.findIndex(r => r.__index === id);
        return idx >= 0 ? idx : rowIndex;
      } catch {
        return rowIndex;
      }
    })();

    setFieldsToRevalidate(prev => {
      const newMap = new Map(prev);
      const existingFields = newMap.get(originalIndex) || [];

      if (fieldKey && !existingFields.includes(fieldKey)) {
        newMap.set(originalIndex, [...existingFields, fieldKey]);
      } else if (!fieldKey) {
        newMap.set(originalIndex, existingFields);
      }

      return newMap;
    });
  }, [data, filteredData]);

  // Add a ref to track the last validation time

  // Trigger revalidation only for specifically marked fields
  useEffect(() => {
    if (fieldsToRevalidate.size === 0) return;

    // Extract rows and fields map
    const rowsToRevalidate = Array.from(fieldsToRevalidate.keys());
    const fieldsMap: {[rowIndex: number]: string[]} = {};
    fieldsToRevalidate.forEach((fields, rowIndex) => {
      fieldsMap[rowIndex] = fields;
    });

    // Clear the revalidation map
    setFieldsToRevalidate(new Map());

    // Revalidate each row with specific fields information
    revalidateRows(rowsToRevalidate, fieldsMap);
  }, [fieldsToRevalidate, revalidateRows]);

  // Function to fetch field options for template form
  const fetchFieldOptions = useCallback(async () => {
    try {
      const response = await axios.get('/api/import/field-options');
      
      // Check if suppliers are included in the response
      if (response.data && response.data.suppliers) {
      } else {
        console.warn('No suppliers found in field options response');
      }
      
      setFieldOptions(response.data);
      return response.data;
    } catch (error) {
      console.error('Error fetching field options:', error);
      toast.error('Failed to load field options');
      return null;
    }
  }, []);

  useEffect(() => {
    if (!fieldOptions) {
      fetchFieldOptions();
    }
  }, [fieldOptions, fetchFieldOptions]);

  // Function to prepare row data for the template form
  const prepareRowDataForTemplateForm = useCallback(() => {
    // Get the selected row key (should be only one)
    const selectedKey = Object.entries(rowSelection)
      .filter(([_, selected]) => selected === true)
      .map(([key, _]) => key)[0];
    
    if (!selectedKey) return null;

    // Try to find the row in the data array
    let selectedRow;
    
    // First check if the key is an index in filteredData
    const numericIndex = parseInt(selectedKey);
    if (!isNaN(numericIndex) && numericIndex >= 0 && numericIndex < filteredData.length) {
      selectedRow = filteredData[numericIndex];
    }
    
    // If not found by index, try to find it by __index property
    if (!selectedRow) {
      selectedRow = data.find(row => row.__index === selectedKey);
    }
    
    // If still not found, return null
    if (!selectedRow) {
      console.error('Selected row not found:', selectedKey);
      return null;
    }
    
    // TemplateForm expects supplier as a NUMBER - the field options have numeric values
    // Convert the supplier to a number if possible
    let supplierValue;
    if (selectedRow.supplier) {
      const numSupplier = Number(selectedRow.supplier);
      supplierValue = !isNaN(numSupplier) ? numSupplier : selectedRow.supplier;
    } else {
      supplierValue = undefined;
    }
    
    // Create template form data with the correctly typed supplier value
    return {
      company: selectedRow.company || '',
      product_type: selectedRow.product_type || '',
      supplier: supplierValue,
      msrp: selectedRow.msrp ? Number(Number(selectedRow.msrp).toFixed(2)) : undefined,
      cost_each: selectedRow.cost_each ? Number(Number(selectedRow.cost_each).toFixed(2)) : undefined,
      qty_per_unit: selectedRow.qty_per_unit ? Number(selectedRow.qty_per_unit) : undefined,
      case_qty: selectedRow.case_qty ? Number(selectedRow.case_qty) : undefined,
      hts_code: selectedRow.hts_code || undefined,
      description: selectedRow.description || undefined,
      weight: selectedRow.weight ? Number(Number(selectedRow.weight).toFixed(2)) : undefined,
      length: selectedRow.length ? Number(Number(selectedRow.length).toFixed(2)) : undefined,
      width: selectedRow.width ? Number(Number(selectedRow.width).toFixed(2)) : undefined,
      height: selectedRow.height ? Number(Number(selectedRow.height).toFixed(2)) : undefined,
      tax_cat: selectedRow.tax_cat ? String(selectedRow.tax_cat) : undefined,
      size_cat: selectedRow.size_cat ? String(selectedRow.size_cat) : undefined,
      categories: Array.isArray(selectedRow.categories) ? selectedRow.categories : 
                 (selectedRow.categories ? [selectedRow.categories] : []),
      ship_restrictions: selectedRow.ship_restrictions ? String(selectedRow.ship_restrictions) : undefined
    };
  }, [data, filteredData, rowSelection]);

  // Add useEffect to fetch field options when template form opens
  useEffect(() => {
    if (isTemplateFormOpen && !fieldOptions) {
      fetchFieldOptions();
    }
  }, [isTemplateFormOpen, fieldOptions, fetchFieldOptions]);

  // Function to handle opening the template form
  const openTemplateForm = useCallback(async () => {
    const templateData = prepareRowDataForTemplateForm();
    if (!templateData) return;
    
    setTemplateFormInitialData(templateData);
    
    // Always fetch fresh field options to ensure supplier list is up to date
    try {
      const options = await fetchFieldOptions();
      if (options && options.suppliers) {
        
        setIsTemplateFormOpen(true);
      } else {
        console.error('Failed to load suppliers for template form');
        toast.error('Could not load supplier options');
      }
    } catch (error) {
      console.error('Error loading field options:', error);
      toast.error('Failed to prepare template form');
    }
  }, [prepareRowDataForTemplateForm, fetchFieldOptions]);

  // Create a function to validate uniqueness if validateUniqueItemNumbers is not available

  // Apply item numbers to data and trigger revalidation for uniqueness

  // Handle next button click - memoized
  const handleNext = useCallback(() => {
    // Make sure any pending item numbers are applied
    upcValidation.applyItemNumbersToData(updatedRowIds => {
      // Mark updated rows for revalidation
      updatedRowIds.forEach(rowIndex => {
        markRowForRevalidation(rowIndex, 'item_number');
      });
      
      // Small delay to ensure all validations complete before proceeding
      setTimeout(() => {
        // Call the onNext callback with the validated data
        onNext?.(data);
      }, 100);
    });
    
    // If no item numbers to apply, just proceed
    if (upcValidation.validatingRows.size === 0) {
      onNext?.(data);
    }
  }, [onNext, data, upcValidation, markRowForRevalidation]);
  
  const deleteSelectedRows = useCallback(() => {
    // Get selected row keys (which may be UUIDs)
    const selectedKeys = Object.entries(rowSelection)
      .filter(([_, selected]) => selected === true)
      .map(([key, _]) => key);
      
    
    if (selectedKeys.length === 0) {
      toast.error("No rows selected");
      return;
    }
    
    // Map UUID keys to array indices
    const selectedIndices = selectedKeys.map(key => {
      // Find the matching row index in the data array
      const index = data.findIndex(row => 
        (row.__index && row.__index === key) || // Match by __index
        (String(data.indexOf(row)) === key)     // Or by numeric index
      );
      return index;
    }).filter(index => index !== -1); // Filter out any not found
    
    
    if (selectedIndices.length === 0) {
      toast.error('Could not find selected rows');
      return;
    }
    
    // Sort indices in descending order to avoid index shifting during removal
    const sortedIndices = [...selectedIndices].sort((a, b) => b - a);
    
    // Create a new array without the selected rows
    const newData = [...data];
    
    // Remove rows from bottom up to avoid index issues
    sortedIndices.forEach(index => {
      if (index >= 0 && index < newData.length) {
        newData.splice(index, 1);
      }
    });
    
    // Update the data with rows removed
    setData(newData);
    
    // Clear row selection
    setRowSelection({});
    
    // Show success message
    toast.success(
      selectedIndices.length === 1 
        ? "Row deleted" 
        : `${selectedIndices.length} rows deleted`
    );
    
    // Reindex the data in the next render cycle
    requestAnimationFrame(() => {
      // Update indices to maintain consistency
      setData(current => 
        current.map((row, newIndex) => ({
          ...row,
          __index: String(newIndex)
        }))
      );
    });
  }, [data, rowSelection, setData, setRowSelection]);
  
  // Memoize handlers
  // This function is defined for potential future use but not currently used
  // eslint-disable-next-line @typescript-eslint/no-unused-vars

  const handleRowSelectionChange = useCallback(
    (value: React.SetStateAction<RowSelectionState>) => {
      setRowSelection(value);
    },
    [setRowSelection]
  );

  // Track if we're currently validating a UPC

  // Track last UPC update to prevent conflicting changes

  // Add these ref declarations here, at component level

  // Helper: Process field value transformations
  const processFieldValue = useCallback((key: T, value: any): any => {
    let processedValue = value;

    // Clean price fields
    if ((key === 'msrp' || key === 'cost_each') && value !== undefined && value !== null) {
      processedValue = cleanPriceField(value);
    }

    // Normalize country code
    if (key === 'coo' && typeof value === 'string' && value.trim()) {
      const normalized = normalizeCountryCode(value);
      if (normalized) {
        processedValue = normalized;
      } else {
        const trimmed = value.trim();
        if (trimmed.length === 2) {
          processedValue = trimmed.toUpperCase();
        }
      }
    }

    if ((key === 'upc' || key === 'barcode') && value !== undefined && value !== null) {
      const { corrected } = correctUpcValue(value);
      processedValue = corrected;
    }

    return processedValue;
  }, []);

  // Helper: Handle company change side effects
  const handleCompanyChange = useCallback((rowIndex: number, rowId: any, companyId: string) => {
    // Clear line/subline values
    setData(prevData => {
      const newData = [...prevData];
      const idx = newData.findIndex(item => item.__index === rowId);
      if (idx >= 0) {
        newData[idx] = {
          ...newData[idx],
          line: undefined,
          subline: undefined
        };
      } else if (rowIndex >= 0 && rowIndex < newData.length) {
        // Fallback if __index is not yet present on the row
        newData[rowIndex] = {
          ...newData[rowIndex],
          line: undefined,
          subline: undefined
        };
      }
      return newData;
    });

    // Fetch product lines
    setValidatingCells(prev => new Set(prev).add(`${rowIndex}-line`));

    setTimeout(() => {
      // Use __index when available, otherwise fall back to the UI row index
      const rowKey = (rowId !== undefined && rowId !== null) ? rowId : rowIndex;
      fetchProductLines(rowKey, companyId)
        .catch(err => {
          console.error(`Error fetching product lines for company ${companyId}:`, err);
          toast.error("Failed to load product lines");
        })
        .finally(() => {
          setValidatingCells(prev => {
            const newSet = new Set(prev);
            newSet.delete(`${rowIndex}-line`);
            return newSet;
          });
        });
    }, 100);
  }, [setData, fetchProductLines]);

  // Helper: Handle line change side effects
  const handleLineChange = useCallback((rowIndex: number, rowId: any, lineId: string) => {
    // Clear subline value
    setData(prevData => {
      const newData = [...prevData];
      const idx = newData.findIndex(item => item.__index === rowId);
      if (idx >= 0) {
        newData[idx] = {
          ...newData[idx],
          subline: undefined
        };
      } else if (rowIndex >= 0 && rowIndex < newData.length) {
        // Fallback if __index is not yet present on the row
        newData[rowIndex] = {
          ...newData[rowIndex],
          subline: undefined
        };
      } else {
        console.warn(`Could not find row with ID ${rowId} to clear subline values`);
      }
      return newData;
    });

    // Fetch sublines
    setValidatingCells(prev => new Set(prev).add(`${rowIndex}-subline`));

    // Use __index when available, otherwise fall back to the UI row index
    const rowKey = (rowId !== undefined && rowId !== null) ? rowId : rowIndex;
    fetchSublines(rowKey, lineId)
      .catch(err => {
        console.error(`Error fetching sublines for line ${lineId}:`, err);
        toast.error("Failed to load sublines");
      })
      .finally(() => {
        setValidatingCells(prev => {
          const newSet = new Set(prev);
          newSet.delete(`${rowIndex}-subline`);
          return newSet;
        });
      });
  }, [setData, fetchSublines]);

  // Helper: Handle UPC validation
  const handleUpcValidation = useCallback((rowIndex: number, supplier: string, upc: string) => {
    const cellKey = `${rowIndex}-item_number`;
    setValidatingCells(prev => new Set(prev).add(cellKey));

    upcValidation.validateUpc(rowIndex, supplier, upc)
      .then(result => {
        if (result.success) {
          upcValidation.applyItemNumbersToData();
          setTimeout(() => markRowForRevalidation(rowIndex, 'item_number'), 50);
        }
      })
      .catch(err => console.error("Error validating UPC:", err))
      .finally(() => {
        setValidatingCells(prev => {
          const newSet = new Set(prev);
          newSet.delete(cellKey);
          return newSet;
        });
      });
  }, [upcValidation, markRowForRevalidation]);

  // Main update handler - simplified to focus on core logic
  const handleUpdateRow = useCallback(async (rowIndex: number, key: T, value: any) => {
    // Process value transformations
    const processedValue = processFieldValue(key, value);

    // Find the row in the data
    const rowData = filteredData[rowIndex];
    if (!rowData) {
      console.error(`No row data found for index ${rowIndex}`);
      return;
    }

    // Use __index to find the actual row in the full data array
    const rowId = rowData.__index;
    const originalIndex = data.findIndex(item => item.__index === rowId);
    const idx = originalIndex >= 0 ? originalIndex : rowIndex;

    // Update the row with validation
    updateRow(idx, key as unknown as any, processedValue);

    // Handle secondary effects asynchronously
    requestAnimationFrame(() => {
      if (key === 'company' && value) {
        handleCompanyChange(rowIndex, rowId, value.toString());
      }

      if (key === 'line' && value) {
        handleLineChange(rowIndex, rowId, value.toString());
      }

      if (key === 'supplier' && value) {
        const upcValue = (data[rowIndex] as any)?.upc || (data[rowIndex] as any)?.barcode;
        if (upcValue) {
          const normalized = correctUpcValue(upcValue).corrected;
          if (normalized) {
            handleUpcValidation(rowIndex, value.toString(), normalized);
          }
        }
      }

      if ((key === 'upc' || key === 'barcode') && processedValue) {
        const supplier = (data[rowIndex] as any)?.supplier;
        if (supplier) {
          const normalized = correctUpcValue(processedValue).corrected;
          if (normalized) {
            handleUpcValidation(rowIndex, supplier.toString(), normalized);
          }
        }
      }
    });
  }, [data, filteredData, updateRow, processFieldValue, handleCompanyChange, handleLineChange, handleUpcValidation]);
  
  // Copy-down that keeps validations in sync for all affected rows
  const handleCopyDown = useCallback((rowIndex: number, fieldKey: string, endRowIndex?: number) => {
    const getActualIndex = (filteredIndex: number) => {
      const filteredRow = filteredData[filteredIndex] as Record<string, any> | undefined
      if (!filteredRow) return -1
      const rowId = filteredRow.__index
      if (rowId === undefined || rowId === null) return -1
      const actualIndex = dataIndexByRowId.get(rowId)
      return actualIndex === undefined ? -1 : actualIndex
    }

    const sourceActualIndex = getActualIndex(rowIndex)
    if (sourceActualIndex < 0) {
      console.error(`Unable to resolve source index ${rowIndex} for copyDown`)
      return
    }

    const sourceRow = data[sourceActualIndex] as Record<string, any> | undefined
    if (!sourceRow) {
      console.error(`Source row ${sourceActualIndex} not found for copyDown`)
      return
    }

    const baseValue = sourceRow[fieldKey]
    const cloneValue = (value: any) => {
      if (Array.isArray(value)) return [...value]
      if (value && typeof value === 'object') return { ...value }
      return value
    }

    const maxFilteredIndex = filteredData.length - 1
    const lastFilteredIndex = endRowIndex !== undefined ? Math.min(endRowIndex, maxFilteredIndex) : maxFilteredIndex
    if (lastFilteredIndex <= rowIndex) return

    const updatedRows = new Set<number>()
    updatedRows.add(sourceActualIndex)

    const snapshot = data.map((row) => ({ ...row })) as RowData<T>[]

    for (let idx = rowIndex + 1; idx <= lastFilteredIndex; idx++) {
      const targetActualIndex = getActualIndex(idx)
      if (targetActualIndex < 0) continue

      updatedRows.add(targetActualIndex)
      snapshot[targetActualIndex] = {
        ...snapshot[targetActualIndex],
        [fieldKey]: cloneValue(baseValue)
      }

      updateRow(targetActualIndex, fieldKey as T, cloneValue(baseValue))
    }

    const affectedIndexes = Array.from(updatedRows)
    const fieldsMap: { [rowIndex: number]: string[] } = {}
    affectedIndexes.forEach((idx) => {
      fieldsMap[idx] = [fieldKey]
    })

    revalidateRows(affectedIndexes, fieldsMap, snapshot)
  }, [data, dataIndexByRowId, filteredData, updateRow, revalidateRows])
  
  // Memoize the rendered validation table
  const renderValidationTable = useMemo(() => {
    // Create wrapper for applyTemplate that matches the expected interface
    const applyTemplateWrapper = (templateId: string, rowIndexes: number[]) => {
      if (rowIndexes.length === 1) {
        // Single row apply - pass the array with a single index
        applyTemplate(templateId, rowIndexes);
      } else if (rowIndexes.length > 1) {
        // Multiple rows - use applyTemplateToSelected
        applyTemplateToSelected(templateId);
      }
    };

    return (
      <UpcValidationTableAdapter
        data={filteredData}
        fields={fields as unknown as Fields<string>}
        validationErrors={validationErrors}
        rowSelection={rowSelection}
        setRowSelection={handleRowSelectionChange}
        updateRow={handleUpdateRow}
        filters={filters}
        templates={templates}
        applyTemplate={applyTemplateWrapper}
        editingCells={editingCells}
        setEditingCells={setEditingCells}
        getTemplateDisplayText={getTemplateDisplayText}
        isValidatingUpc={isRowValidatingUpc}
        validatingUpcRows={Array.from(upcValidation.validatingRows)}
        copyDown={handleCopyDown}
        validatingCells={validatingCells}
        isLoadingTemplates={isLoadingTemplates}
        rowProductLines={rowProductLines}
        rowSublines={rowSublines}
        isLoadingLines={isLoadingLines}
        isLoadingSublines={isLoadingSublines}
        upcValidation={upcValidation}
        itemNumbers={upcValidation.itemNumbers}
      />
    );
  }, [
    filteredData,
    fields,
    validationErrors,
    rowSelection,
    handleRowSelectionChange,
    handleUpdateRow,
    filters,
    templates,
    applyTemplate,
    applyTemplateToSelected,
    getTemplateDisplayText,
    isRowValidatingUpc,
    upcValidation,
    handleCopyDown,
    validatingCells,
    isLoadingTemplates,
    rowProductLines,
    rowSublines,
    isLoadingLines,
    isLoadingSublines
  ]);

  // Show loading state during initialization
  if (isInitializing) {
    // Convert initializationTasks object to array format
    const tasksArray = Object.values(initializationTasks).map(task => ({
      label: task.label,
      status: task.status as 'pending' | 'in_progress' | 'completed' | 'failed'
    }));

    return (
      <InitializingValidation
        totalRows={data.length}
        tasks={tasksArray}
      />
    );
  }

  return (
    <div
      className="flex flex-col h-[calc(100vh-10rem)] overflow-hidden"
      onMouseUp={() => {
        // Prevent stray text selection when clicking away from cells
        try {
          const sel = window.getSelection?.();
          if (sel && sel.type === 'Range') {
            sel.removeAllRanges();
          }
        } catch {}
      }}
    >
      <div className="flex-1 overflow-hidden">
        <div className="flex h-[calc(100vh-9.5rem)] flex-col">
          <div className="flex-1 overflow-hidden">
            <div className="h-full flex flex-col">
              {/* Header section */}
              <div className="px-8 pt-6">
                <div className="mb-6 flex flex-col gap-4">
                  <div className="flex flex-wrap items-center justify-between">
                    <h2 className="text-2xl font-semibold text-foreground">
                      {translations.validationStep.title || "Validate Data"}
                    </h2>
                    
                    <div className="flex items-center gap-4">
                      {isFromScratch && (
                        <Button 
                          variant="outline"
                          onClick={() => {
                            // Create a new empty row
                            const newRow = {} as any;
                            // Add __index property with a unique string id
                            newRow.__index = `row-${Date.now()}`;
                            // Add the new row and validate
                            const newData = [...data, newRow];
                            setData(newData);
                          }}
                          className="flex items-center gap-1"
                        >
                          <Plus className="h-4 w-4" />
                          Add Row
                        </Button>
                      )}
                      <Button 
                        variant="outline"
                        onClick={() => setIsProductSearchDialogOpen(true)}
                        className="flex items-center gap-1"
                      >
                        <Edit3 className="h-4 w-4" />
                        Create New Template
                      </Button>
                      <CreateProductCategoryDialog
                        trigger={
                          <Button variant="outline" className="flex items-center gap-1">
                            <Plus className="h-4 w-4" />
                            New Line/Subline
                          </Button>
                        }
                        companies={fieldOptions?.companies || []}
                        defaultCompanyId={selectedRowCategoryDefaults.company}
                        defaultLineId={selectedRowCategoryDefaults.line}
                        onCreated={handleValidationCategoryCreated}
                      />
                      <div className="flex items-center gap-2">
                        <Switch
                          checked={filters.showErrorsOnly}
                          onCheckedChange={(checked) => updateFilters({ showErrorsOnly: checked })}
                          id="filter-errors"
                        />
                        <label htmlFor="filter-errors" className="text-sm text-muted-foreground">
                          {translations.validationStep.filterSwitchTitle || "Show only rows with errors"}
                        </label>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
              
              {/* Main table section */}
              <div className="px-8 pb-6 flex-1 min-h-0">
                <div className="rounded-md border h-full flex flex-col overflow-hidden">
                  <div className="flex-1 overflow-hidden w-full">
                    <div
                      className="overflow-auto max-h-[calc(100vh-320px)] w-full"
                      style={{
                        scrollBehavior: 'smooth',
                        willChange: 'transform',
                        position: 'relative',
                        WebkitOverflowScrolling: 'touch', // Improve scroll performance on Safari
                        overscrollBehavior: 'contain', // Prevent scroll chaining
                        contain: 'paint', // Improve performance for sticky elements
                         }}
                    >
                      {renderValidationTable}
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
          
          {/* Selection Action Bar - only shown when items are selected */}
          {Object.keys(rowSelection).length > 0 && (
            <div className="fixed bottom-24 left-1/2 transform -translate-x-1/2 z-50 animate-in fade-in slide-in-from-bottom-5 duration-300">
              <div className="bg-card shadow-xl rounded-2xl border border-gray-200 px-4 py-3 flex items-center gap-3">
                <div className="flex items-center gap-2">
                  <div className="mr-3 bg-muted shadow-xs items-center flex text-primary pl-2 pr-7 h-8 flex-shrink-0 rounded-md text-xs font-medium border border-muted">
                    {Object.keys(rowSelection).length} selected
                  </div>
                          
                  <Button
                    variant="ghost"
                    size="icon"
                    onClick={() => setRowSelection({})}
                    className="h-8 w-8 -ml-[48px] hover:bg-transparent hover:text-muted-foreground"
                    title="Clear selection"
                  >
                    <X className="h-4 w-4" />
                  </Button>
                </div>
                
                <div className="flex items-center ml-2 mr-1 shadow-xs">
                  {isLoadingTemplates ? (
                    <Button variant="outline" className="w-[250px] justify-between h-8" disabled>
                      <Skeleton className="h-4 w-full" />
                    </Button>
                  ) : templates && templates.length > 0 ? (
                    <SearchableTemplateSelect
                      templates={templates}
                      value={selectedTemplateId || ""}
                      onValueChange={(value) => {
                        if (value) {
                          applyTemplateToSelected(value);
                        }
                      }}
                      getTemplateDisplayText={getTemplateDisplayText}
                      placeholder="Apply template to selected rows"
                      triggerClassName="w-[250px] text-xs h-8"
                    />
                  ) : (
                    <Button variant="outline" className="w-full justify-between text-xs" disabled>
                      No templates available
                    </Button>
                  )}
                </div>
                
                {Object.keys(rowSelection).length === 1 && (
                  <Button
                    variant="outline"
                    size="sm"
                    onClick={openTemplateForm}
                    className="h-8 mr-1 shadow-xs"
                  >
                    Save as template
                  </Button>
                )}
                
                <Button 
                  variant={"destructive"}
                  size="sm"
                  className="h-8 shadow-xs"
                  onClick={() => {
                    deleteSelectedRows();
                  }}
                >
                  {isFromScratch ? "Delete Row" : translations.validationStep.discardButtonTitle || "Discard Row"}
                </Button>
              </div>
            </div>
          )}
        </div>
      </div>
      
      {/* Footer with navigation buttons */}
      <div className="border-t bg-muted px-8 py-4">
        <div className="flex items-center justify-between">
          {onBack && (
            <Button variant="outline" onClick={onBack}>
              {translations.validationStep.backButtonTitle || "Back"}
            </Button>
          )}
          <div className="flex items-center gap-2">
            {/* Show Prompt Button */}
            <Protected permission="admin:debug">
              <Button 
                variant="outline" 
                onClick={aiValidation.showCurrentPrompt}
                disabled={aiValidation.isAiValidating}
                className="flex items-center gap-1"
              >
                <FileText className="h-4 w-4" />
                Show Prompt
              </Button>
            </Protected>
            
            {/* AI Validate Button */}
            <Button 
              variant="outline" 
              onClick={aiValidation.handleAiValidation}
              disabled={aiValidation.isAiValidating || data.length === 0}
              className="flex items-center gap-1"
            >
              {aiValidation.isAiValidating ? (
                <>
                  <Loader2 className="h-4 w-4 animate-spin" />
                  Validating...
                </>
              ) : (
                <>
                  <Sparkles className="h-4 w-4" />
                  AI Validate
                </>
              )}
            </Button>
            
            <Button 
               onClick={handleNext}
            >
              {translations.validationStep.nextButtonTitle || "Next"}
            </Button>
          </div>
        </div>
      </div>
      
      {/* AI Validation Dialogs */}
      <AiValidationDialogs
        aiValidationProgress={aiValidation.aiValidationProgress}
        aiValidationDetails={aiValidation.aiValidationDetails}
        currentPrompt={aiValidation.currentPrompt}
        setAiValidationProgress={aiValidation.setAiValidationProgress}
        setAiValidationDetails={aiValidation.setAiValidationDetails}
        setCurrentPrompt={aiValidation.setCurrentPrompt}
        revertAiChange={aiValidation.revertAiChange}
        isChangeReverted={aiValidation.isChangeReverted}
        getFieldDisplayValueWithHighlight={aiValidation.getFieldDisplayValueWithHighlight}
        fields={fields}
        debugData={aiValidation.currentPrompt.debugData}
      />
      
      {/* Product Search Dialog */}
      <SearchProductTemplateDialog
        isOpen={isProductSearchDialogOpen}
        onClose={() => setIsProductSearchDialogOpen(false)}
        onTemplateCreated={loadTemplates}
      />

      {/* Template Form Dialog */}
      <TemplateForm
        isOpen={isTemplateFormOpen}
        onClose={() => setIsTemplateFormOpen(false)}
        onSuccess={() => {
          loadTemplates();
          setIsTemplateFormOpen(false);
        }}
        initialData={templateFormInitialData}
        mode="create"
        fieldOptions={fieldOptions}
      />
    </div>
  )
}

export default ValidationContainer
