import React, { useState, useEffect, useRef, useCallback, useMemo, useLayoutEffect } from 'react'
import { useValidationState } from '../hooks/useValidationState'
import { Props } 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 axios from 'axios'
import { RowSelectionState } from '@tanstack/react-table'
import { useUpcValidation } from '../hooks/useUpcValidation'
import { useProductLinesFetching } from '../hooks/useProductLinesFetching'
import UpcValidationTableAdapter from './UpcValidationTableAdapter'
import { Skeleton } from '@/components/ui/skeleton'
import { Protected } from '@/components/auth/Protected'
/**
 * 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,
    isLoadingTemplates,
    validatingCells,
    setValidatingCells
  } = validationState
  
  // Use product lines fetching hook
  const {
    rowProductLines,
    rowSublines,
    isLoadingLines,
    isLoadingSublines,
    fetchProductLines,
    fetchSublines
  } = useProductLinesFetching(data);
  
  // Use UPC validation hook
  const upcValidation = useUpcValidation(data, setData);
  
  // 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
  );
  
  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)

  // Track fields that need revalidation due to value changes
  const [fieldsToRevalidate, setFieldsToRevalidate] = useState<Set<number>>(new Set());
  const [fieldsToRevalidateMap, setFieldsToRevalidateMap] = useState<{[rowIndex: number]: string[]}>({});

  // Function to mark a row for revalidation
  const markRowForRevalidation = useCallback((rowIndex: number, fieldKey?: string) => {
    setFieldsToRevalidate(prev => {
      const newSet = new Set(prev);
      newSet.add(rowIndex);
      return newSet;
    });
    
    // Also track which specific field needs to be revalidated
    if (fieldKey) {
      setFieldsToRevalidateMap(prev => {
        const newMap = { ...prev };
        if (!newMap[rowIndex]) {
          newMap[rowIndex] = [];
        }
        if (!newMap[rowIndex].includes(fieldKey)) {
          newMap[rowIndex] = [...newMap[rowIndex], fieldKey];
        }
        return newMap;
      });
    }
  }, []);

  // Add a ref to track the last validation time
  
  // Trigger revalidation only for specifically marked fields
  useEffect(() => {
    if (fieldsToRevalidate.size === 0) return;
    
    // Revalidate the marked rows
    const rowsToRevalidate = Array.from(fieldsToRevalidate);
    
    // Clear the revalidation set
    setFieldsToRevalidate(new Set());
    
    // Get the fields map for revalidation
    const fieldsMap = { ...fieldsToRevalidateMap };
    
    // Clear the fields map
    setFieldsToRevalidateMap({});
    
    console.log(`Validating ${rowsToRevalidate.length} rows with specific fields`);
    
    // Revalidate each row with specific fields information
    validationState.revalidateRows(rowsToRevalidate, fieldsMap);
  }, [fieldsToRevalidate, validationState, fieldsToRevalidateMap]);

  // Function to fetch field options for template form
  const fetchFieldOptions = useCallback(async () => {
    try {
      const response = await axios.get('/api/import/field-options');
      console.log('Field options from API:', response.data);
      
      // Check if suppliers are included in the response
      if (response.data && response.data.suppliers) {
        console.log('Suppliers available:', response.data.suppliers.length);
      } 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;
    }
  }, []);

  // 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) {
        console.log(`Loaded ${options.suppliers.length} suppliers for template form`);
        
        // Log if we can find a match for our supplier
        if (templateData.supplier !== undefined) {
          // Need to compare numeric values since supplier options have numeric values
          const supplierMatch = options.suppliers.find((s: { value: string | number }) => 
            s.value === templateData.supplier || 
            Number(s.value) === Number(templateData.supplier)
          );
          
          console.log('Found supplier match:', supplierMatch ? 'Yes' : 'No', 
                      'For supplier value:', templateData.supplier, 
                      'Type:', typeof templateData.supplier);
                      
          if (supplierMatch) {
            console.log('Matched supplier:', supplierMatch.label);
          }
        }
        
        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);
    
    console.log('Selected row keys for deletion:', selectedKeys);
    
    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
    
    console.log('Mapped row indices for deletion:', selectedIndices);
    
    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]
  );

  // Add scroll container ref at the container level
  const scrollContainerRef = useRef<HTMLDivElement>(null);
  const lastScrollPosition = useRef({ left: 0, top: 0 });
  
  // Track if we're currently validating a UPC

  // Track last UPC update to prevent conflicting changes

  // Add these ref declarations here, at component level

  // Memoize scroll handlers - simplified to avoid performance issues
  const handleScroll = useCallback((event: React.UIEvent<HTMLDivElement> | Event) => {
    // Store scroll position directly without conditions
    const target = event.currentTarget as HTMLDivElement;
    lastScrollPosition.current = {
      left: target.scrollLeft,
      top: target.scrollTop
    };
  }, []);

  // Add scroll event listener
  useEffect(() => {
    const container = scrollContainerRef.current;
    if (container) {
      // Convert React event handler to native event handler
      const nativeHandler = ((evt: Event) => {
        handleScroll(evt);
      }) as EventListener;
      
      container.addEventListener('scroll', nativeHandler, { passive: true });
      return () => container.removeEventListener('scroll', nativeHandler);
    }
  }, [handleScroll]);

  // Use a ref to track if we need to restore scroll position
  const needScrollRestore = useRef(false);

  // Set flag when data changes
  useEffect(() => {
    needScrollRestore.current = true;
    // Only restore scroll on layout effects to avoid triggering rerenders
  }, []);

  // Use layout effect for DOM manipulations
  useLayoutEffect(() => {
    if (!needScrollRestore.current) return;
    
    const container = scrollContainerRef.current;
    if (container && (lastScrollPosition.current.left > 0 || lastScrollPosition.current.top > 0)) {
      container.scrollLeft = lastScrollPosition.current.left;
      container.scrollTop = lastScrollPosition.current.top;
      needScrollRestore.current = false;
    }
  }, []);

  // Ensure manual edits to item numbers persist with minimal changes to validation logic
  const handleUpdateRow = useCallback(async (rowIndex: number, key: T, value: any) => {
    // Process value before updating data
    let processedValue = value;
    
    // Strip dollar signs from price fields
    if ((key === 'msrp' || key === 'cost_each') && typeof value === 'string') {
      processedValue = value.replace(/[$,]/g, '');
      
      // Also ensure it's a valid number
      const numValue = parseFloat(processedValue);
      if (!isNaN(numValue)) {
        processedValue = numValue.toFixed(2);
      }
    }
    
    // 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);
    
    // Detect if this is a direct item_number edit
    const isItemNumberEdit = key === 'item_number' as T;
    
    // For item_number edits, we need special handling to ensure they persist
    if (isItemNumberEdit) {
      console.log(`Manual edit to item_number: ${value}`);
      
      // First, update data immediately to ensure edit takes effect
      setData(prevData => {
        const newData = [...prevData];
        if (originalIndex >= 0 && originalIndex < newData.length) {
          newData[originalIndex] = {
            ...newData[originalIndex],
            [key]: processedValue
          };
        }
        return newData;
      });
      
      // Mark for revalidation after a delay to ensure data update completes first
      setTimeout(() => {
        markRowForRevalidation(rowIndex, key as string);
      }, 0);
      
      // Return early to prevent double-updating
      return;
    }
    
    // For all other fields, use standard approach
    // Always use setData for updating - immediate update for better UX
    const updatedRow = { ...rowData, [key]: processedValue };
    
    // Mark this row for revalidation to clear any existing errors
    markRowForRevalidation(rowIndex, key as string);
    
    // Update the data immediately to show the change
    setData(prevData => {
      const newData = [...prevData];
      if (originalIndex >= 0 && originalIndex < newData.length) {
        // Create a new row object with the updated field
        newData[originalIndex] = {
          ...newData[originalIndex],
          [key]: processedValue
        };
      }
      return newData;
    });
    
    // Secondary effects - using a timeout to ensure UI updates first
    setTimeout(() => {
      // Handle company change - clear line/subline and fetch product lines
      if (key === 'company' && value) {
        console.log(`Company changed to ${value} for row ${rowIndex}, updating lines and sublines`);
        
        // Clear any existing line/subline values immediately
        setData(prevData => {
          const newData = [...prevData];
          const idx = newData.findIndex(item => item.__index === rowId);
          if (idx >= 0) {
            console.log(`Clearing line and subline values for row with ID ${rowId}`);
            newData[idx] = {
              ...newData[idx],
              line: undefined,
              subline: undefined
            };
          } else {
            console.warn(`Could not find row with ID ${rowId} to clear line/subline values`);
          }
          return newData;
        });
        
        // Fetch product lines for the new company
        if (rowId && value !== undefined) {
          const companyId = value.toString();
          
          // Force immediate fetch for better UX
          console.log(`Immediately fetching product lines for company ${companyId} for row ${rowId}`);
          
          // Set loading state first
          setValidatingCells(prev => {
            const newSet = new Set(prev);
            newSet.add(`${rowIndex}-line`);
            return newSet;
          });
          
          fetchProductLines(rowId, companyId)
            .then(lines => {
              console.log(`Successfully loaded ${lines.length} product lines for company ${companyId}`);
            })
            .catch(err => {
              console.error(`Error fetching product lines for company ${companyId}:`, err);
              toast.error("Failed to load product lines");
            })
            .finally(() => {
              // Clear loading indicator
              setValidatingCells(prev => {
                const newSet = new Set(prev);
                newSet.delete(`${rowIndex}-line`);
                return newSet;
              });
            });
        }
      }
      
      // Handle supplier + UPC validation - using the most recent values
      if (key === 'supplier' && value) {
        // Get the latest UPC value from the updated row
        const upcValue = updatedRow.upc || updatedRow.barcode;
        
        if (upcValue) {
          console.log(`Validating UPC: rowIndex=${rowIndex}, supplier=${value}, upc=${upcValue}`);
          
          // Mark the item_number cell as being validated
          const cellKey = `${rowIndex}-item_number`;
          setValidatingCells(prev => {
            const newSet = new Set(prev);
            newSet.add(cellKey);
            return newSet;
          });
          
          // Use a regular promise-based approach instead of await
          upcValidation.validateUpc(rowIndex, value.toString(), upcValue.toString())
            .then(result => {
              if (result.success) {
                console.log(`UPC validation successful for row ${rowIndex}`);
                upcValidation.applyItemNumbersToData();
                
                // Mark for revalidation after item numbers are updated
                setTimeout(() => {
                  markRowForRevalidation(rowIndex, 'item_number');
                }, 50);
              }
            })
            .catch(err => {
              console.error("Error validating UPC:", err);
            })
            .finally(() => {
              // Clear validation state for the item_number cell
              setValidatingCells(prev => {
                const newSet = new Set(prev);
                newSet.delete(cellKey);
                return newSet;
              });
            });
        }
      }
      
      // Handle line change - clear subline and fetch sublines
      if (key === 'line' && value) {
        console.log(`Line changed to ${value} for row ${rowIndex}, updating sublines`);
        
        // Clear any existing subline value
        setData(prevData => {
          const newData = [...prevData];
          const idx = newData.findIndex(item => item.__index === rowId);
          if (idx >= 0) {
            console.log(`Clearing subline values for row with ID ${rowId}`);
            newData[idx] = {
              ...newData[idx],
              subline: undefined
            };
          } else {
            console.warn(`Could not find row with ID ${rowId} to clear subline values`);
          }
          return newData;
        });
        
        // Fetch sublines for the new line
        if (rowId && value !== undefined) {
          const lineId = value.toString();
          
          // Force immediate fetch for better UX
          console.log(`Immediately fetching sublines for line ${lineId} for row ${rowId}`);
          
          // Set loading state first
          setValidatingCells(prev => {
            const newSet = new Set(prev);
            newSet.add(`${rowIndex}-subline`);
            return newSet;
          });
          
          fetchSublines(rowId, lineId)
            .then(sublines => {
              console.log(`Successfully loaded ${sublines.length} sublines for line ${lineId}`);
            })
            .catch(err => {
              console.error(`Error fetching sublines for line ${lineId}:`, err);
              toast.error("Failed to load sublines");
            })
            .finally(() => {
              // Clear loading indicator
              setValidatingCells(prev => {
                const newSet = new Set(prev);
                newSet.delete(`${rowIndex}-subline`);
                return newSet;
              });
            });
        }
      }
      
      // Add the UPC/barcode validation handler back:
      // Handle UPC/barcode + supplier validation
      if ((key === 'upc' || key === 'barcode') && value) {
        // Get latest supplier from the updated row
        const supplier = updatedRow.supplier;
        
        if (supplier) {
          console.log(`Validating UPC from UPC change: rowIndex=${rowIndex}, supplier=${supplier}, upc=${value}`);
          
          // Mark the item_number cell as being validated
          const cellKey = `${rowIndex}-item_number`;
          setValidatingCells(prev => {
            const newSet = new Set(prev);
            newSet.add(cellKey);
            return newSet;
          });
          
          // Use a regular promise-based approach
          upcValidation.validateUpc(rowIndex, supplier.toString(), value.toString())
            .then(result => {
              if (result.success) {
                console.log(`UPC validation successful for row ${rowIndex}`);
                upcValidation.applyItemNumbersToData();
                
                // Mark for revalidation after item numbers are updated
                setTimeout(() => {
                  markRowForRevalidation(rowIndex, 'item_number');
                }, 50);
              }
            })
            .catch(err => {
              console.error("Error validating UPC:", err);
            })
            .finally(() => {
              // Clear validation state for the item_number cell
              setValidatingCells(prev => {
                const newSet = new Set(prev);
                newSet.delete(cellKey);
                return newSet;
              });
            });
        }
      }
    }, 0); // Using 0ms timeout to defer execution until after the UI update
  }, [data, filteredData, setData, fetchProductLines, fetchSublines, upcValidation, markRowForRevalidation]);
  
  // Fix the missing loading indicator clear code
  const handleCopyDown = useCallback((rowIndex: number, fieldKey: string, endRowIndex?: number) => {
    // Get the value to copy from the source row
    const sourceRow = data[rowIndex];
    if (!sourceRow) {
      console.error(`Source row ${rowIndex} not found for copyDown`);
      return;
    }
    
    const valueToCopy = sourceRow[fieldKey];
    
    // Create a proper copy of the value to avoid reference issues, especially for arrays (MultiSelectCell)
    const valueCopy = Array.isArray(valueToCopy) ? [...valueToCopy] : valueToCopy;

    // Get all rows below the source row, up to endRowIndex if specified
    const lastRowIndex = endRowIndex !== undefined ? Math.min(endRowIndex, data.length - 1) : data.length - 1;
    const rowsToUpdate = Array.from({ length: lastRowIndex - rowIndex }, (_, i) => rowIndex + i + 1);
    
    // Mark all cells as updating at once
    const updatingCells = new Set<string>();
    rowsToUpdate.forEach(targetRowIndex => {
      updatingCells.add(`${targetRowIndex}-${fieldKey}`);
    });
    
    setValidatingCells(prev => {
      const newSet = new Set(prev);
      updatingCells.forEach(cell => newSet.add(cell));
      return newSet;
    });

    // Update all rows at once efficiently with a single state update
    setData(prevData => {
      // Create a new copy of the data
      const newData = [...prevData];
      
      // Update all rows at once
      rowsToUpdate.forEach(targetRowIndex => {
        // Find the original row using __index
        const rowData = filteredData[targetRowIndex];
        if (!rowData) return;
        
        const rowId = rowData.__index;
        const originalIndex = newData.findIndex(item => item.__index === rowId);
        
        if (originalIndex !== -1) {
          // Update the specific field on this row
          newData[originalIndex] = {
            ...newData[originalIndex],
            [fieldKey]: valueCopy
          };
        } else {
          // Fall back to direct index if __index not found
          if (targetRowIndex < newData.length) {
            newData[targetRowIndex] = {
              ...newData[targetRowIndex],
              [fieldKey]: valueCopy
            };
          }
        }
      });
      
      return newData;
    });
    
    // Mark rows for revalidation
    rowsToUpdate.forEach(targetRowIndex => {
      markRowForRevalidation(targetRowIndex, fieldKey);
    });
    
    // Clear the loading state for all cells after a short delay
    setTimeout(() => {
      setValidatingCells(prev => {
        if (prev.size === 0) return prev;
        const newSet = new Set(prev);
        updatingCells.forEach(cell => newSet.delete(cell));
        return newSet;
      });
    }, 100);
    
    // If copying UPC or supplier fields, validate UPC for all rows
    if (fieldKey === 'upc' || fieldKey === 'barcode' || fieldKey === 'supplier') {
      // Process each row in parallel
      const validationsToRun: {rowIndex: number, supplier: string, upc: string}[] = [];
      
      // Process each row separately to collect validation tasks
      rowsToUpdate.forEach(targetRowIndex => {
        const rowData = filteredData[targetRowIndex];
        if (!rowData) return;
        
        // Only validate if both UPC and supplier are present after the update
        const updatedRow = {
          ...rowData,
          [fieldKey]: valueCopy
        };
        
        const hasUpc = updatedRow.upc || updatedRow.barcode;
        const hasSupplier = updatedRow.supplier;
        
        if (hasUpc && hasSupplier) {
          const upcValue = updatedRow.upc || updatedRow.barcode;
          const supplierId = updatedRow.supplier;
          
          // Queue this validation if both values are defined
          if (supplierId !== undefined && upcValue !== undefined) {
            validationsToRun.push({
              rowIndex: targetRowIndex,
              supplier: supplierId.toString(),
              upc: upcValue.toString()
            });
          }
        }
      });
      
      // Run validations in parallel but limit the batch size
      if (validationsToRun.length > 0) {
        console.log(`Running ${validationsToRun.length} UPC validations for copyDown`);
        
        // Mark all cells as validating
        validationsToRun.forEach(({ rowIndex }) => {
          const cellKey = `${rowIndex}-item_number`;
          setValidatingCells(prev => {
            const newSet = new Set(prev);
            newSet.add(cellKey);
            return newSet;
          });
        });
        
        // Process in smaller batches to avoid overwhelming the system
        const BATCH_SIZE = 5; // Process 5 validations at a time
        const processBatch = (startIdx: number) => {
          const endIdx = Math.min(startIdx + BATCH_SIZE, validationsToRun.length);
          const batch = validationsToRun.slice(startIdx, endIdx);
          
          Promise.all(
            batch.map(({ rowIndex, supplier, upc }) => 
              upcValidation.validateUpc(rowIndex, supplier, upc)
                .then(result => {
                  if (result.success) {
                    // Apply immediately for better UX
                    if (startIdx + BATCH_SIZE >= validationsToRun.length) {
                      // Apply all updates at the end with callback to mark for revalidation
                      upcValidation.applyItemNumbersToData(updatedRowIds => {
                        // Mark these rows for revalidation after a delay
                        setTimeout(() => {
                          updatedRowIds.forEach(rowIdx => {
                            markRowForRevalidation(rowIdx, 'item_number');
                          });
                        }, 100);
                      });
                    }
                  }
                  return { rowIndex, success: result.success };
                })
                .catch(err => {
                  console.error(`Error validating UPC for row ${rowIndex}:`, err);
                  return { rowIndex, success: false };
                })
                .finally(() => {
                  // Clear validation state for this cell
                  const cellKey = `${rowIndex}-item_number`;
                  setValidatingCells(prev => {
                    if (!prev.has(cellKey)) return prev;
                    const newSet = new Set(prev);
                    newSet.delete(cellKey);
                    return newSet;
                  });
                })
            )
          ).then(() => {
            // If there are more validations to run, process the next batch
            if (endIdx < validationsToRun.length) {
              // Add a small delay between batches to prevent UI freezing
              setTimeout(() => processBatch(endIdx), 100);
            } else {
              console.log(`Completed all ${validationsToRun.length} UPC validations`);
              // Final application of all item numbers if not done by individual batches
              upcValidation.applyItemNumbersToData(updatedRowIds => {
                // Mark these rows for revalidation after a delay
                setTimeout(() => {
                  updatedRowIds.forEach(rowIdx => {
                    markRowForRevalidation(rowIdx, 'item_number');
                  });
                }, 100);
              });
            }
          });
        };
        
        // Start processing the first batch
        processBatch(0);
      }
    }
  }, [data, filteredData, setData, setValidatingCells, upcValidation, markRowForRevalidation]);
  
  // 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}
        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
  ]);

  return (
    <div className="flex flex-col h-[calc(100vh-10rem)] overflow-hidden">
      <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>
                      <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 
                      ref={scrollContainerRef}
                      className="overflow-auto max-h-[calc(100vh-320px)] w-full"
                      style={{ 
                        willChange: 'transform',
                        position: 'relative',
                        WebkitOverflowScrolling: 'touch', // Improve scroll performance on Safari
                        overscrollBehavior: 'contain', // Prevent scroll chaining
                        contain: 'paint', // Improve performance for sticky elements
                         }}
                      onScroll={handleScroll}
                    >
                      {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={() => {
                    console.log('Delete/Discard button clicked');
                    console.log('Row selection state:', rowSelection);
                    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