/**
 * VariationsTable Component
 * 
 * AG Grid table with variations data, inline editing, infinite scroll
 */

import React, { useRef, useMemo, useCallback, useState, useEffect } from 'react';
import { AgGridReact } from 'ag-grid-react';
import type { ColDef } from 'ag-grid-community';
import { useVariations, useUpdateVariation } from '../../hooks/useVariations';
import { useTranslation } from 'react-i18next';
import toast from 'react-hot-toast';
import type { PreviewData } from '../../types/preview';
import InlineSalePriceEditor from './InlineSalePriceEditor';
import StockStatusModal from './StockStatusModal';
import FilterBar, { type FilterState } from './FilterBar';
import Toolbar from './Toolbar';
import ColumnConfigModal from './ColumnConfigModal';
import { getColumnConfig, saveColumnConfig, getEnabledColumns, type ColumnDefinition, type ColumnId } from '../../types/columns';
import { getColumnDefinition } from './columnDefinitions.tsx';
import { formatPriceRange, type WCSettings } from '../../utils/woocommerce';
import LoadingSpinner from '../ui/LoadingSpinner';

// AG Grid styles
import 'ag-grid-community/styles/ag-grid.css';
import 'ag-grid-community/styles/ag-theme-alpine.css';

interface Props {
  onSelectionChange?: (ids: number[]) => void;
  previewData?: PreviewData;
}

interface SalePriceEditState {
  variationId: number;
  currentPrice: string;
  dateFrom: string | null;
  dateTo: string | null;
  position: { top: number; left: number; width: number; showAbove: boolean };
}

interface StockStatusChangeState {
  variationId: number;
  currentStatus: string;
  newStatus: string;
  oldValue: string;
}

export default function VariationsTable({ onSelectionChange, previewData = {} }: Props) {
  const { t } = useTranslation();
  const gridRef = useRef<AgGridReact>(null);
  const [offset] = useState(0); // eslint-disable-line @typescript-eslint/no-unused-vars
  const limit = 100;
  const [salePriceEdit, setSalePriceEdit] = useState<SalePriceEditState | null>(null);
  const [stockStatusChange, setStockStatusChange] = useState<StockStatusChangeState | null>(null);
  const isRevertingStockStatus = useRef(false); // 🔥 Flag to prevent loop
  const [viewMode, setViewMode] = useState<'flat' | 'grouped'>('grouped');
  const [expandedParents, setExpandedParents] = useState<Set<number>>(new Set());
  const isApplyingCheckedSearch = useRef(false); // 🔥 Flag for checked search
  const isExpandingForSelection = useRef(false); // 🔥 Flag for parent expand + select race condition
  const pendingSelection = useRef<number[]>([]); // 🔥 Pending variation IDs to select after expand
  const [filters, setFilters] = useState<FilterState>({
    search: '',
    attributes: '',
    priceMin: null,
    priceMax: null,
    filterSalePrice: false,
    saleDateFrom: null,
    saleDateTo: null,
    onlyActiveSales: false,
    checkedSearch: false,
  });
  
  // Column configuration
  const [showColumnConfig, setShowColumnConfig] = useState(false);
  const [columnConfig, setColumnConfig] = useState<Record<ColumnId, ColumnDefinition>>(getColumnConfig());
  
  const handleColumnConfigSave = useCallback((newConfig: Record<ColumnId, ColumnDefinition>) => {
    setColumnConfig(newConfig);
    saveColumnConfig(newConfig);
    setShowColumnConfig(false);
    
    // Refresh grid columns
    if (gridRef.current?.api) {
      gridRef.current.api.refreshCells({ force: true });
    }
  }, []);
  
  // 🔥 STABLE filter change handler (prevents infinite loop in FilterBar useEffect)
  const handleFilterChange = useCallback((newFilters: FilterState) => {
    setFilters(prev => ({ ...newFilters, checkedSearch: prev.checkedSearch }));
  }, []);
  
  // 🔥 STABLE checked search handler (prevents checkbox flicker)
  const handleCheckedSearchChange = useCallback((checked: boolean) => {
    setFilters(prev => ({ ...prev, checkedSearch: checked }));
  }, []);
  
  // Fetch variations with filters (grouped mode if enabled)
  const { data, isLoading, isFetching, error } = useVariations({ 
    offset, 
    limit,
    search: filters.search,
    attributes: filters.attributes,
    priceMin: filters.priceMin,
    priceMax: filters.priceMax,
    filterSalePrice: filters.filterSalePrice,
    saleDateFrom: filters.saleDateFrom,
    saleDateTo: filters.saleDateTo,
    onlyActiveSales: filters.onlyActiveSales,
    groupBy: viewMode === 'grouped' ? 'parent' : undefined,
  });
  const updateMutation = useUpdateVariation();

  // Transform grouped data into flat rows for AG Grid
  const buildGroupedRows = useCallback((wcSettings?: WCSettings) => {
    if (!data || viewMode !== 'grouped') {
      return data?.data?.variations || [];
    }

    // Grouped mode: data.data.parents array
    if (!data.data.parents) {
      return [];
    }

    const rows: any[] = [];
    data.data.parents.forEach((parent: any) => {
      // Calculate aggregated data for parent row
      const variations = parent.variations || [];
      const prices = variations.map((v: any) => parseFloat(v.price || 0)).filter((p: number) => p > 0);
      const regularPrices = variations.map((v: any) => parseFloat(v.regular_price || 0)).filter((p: number) => p > 0);
      const salePrices = variations.map((v: any) => parseFloat(v.sale_price || 0)).filter((p: number) => p > 0);
      const stocks = variations.map((v: any) => parseInt(v.stock_quantity || 0, 10));
      
      const minPrice = prices.length > 0 ? Math.min(...prices) : 0;
      const maxPrice = prices.length > 0 ? Math.max(...prices) : 0;
      const minRegularPrice = regularPrices.length > 0 ? Math.min(...regularPrices) : 0;
      const maxRegularPrice = regularPrices.length > 0 ? Math.max(...regularPrices) : 0;
      const minSalePrice = salePrices.length > 0 ? Math.min(...salePrices) : 0;
      const maxSalePrice = salePrices.length > 0 ? Math.max(...salePrices) : 0;
      const totalStock = stocks.reduce((sum: number, qty: number) => sum + qty, 0);
      
      // 🎯 Use WooCommerce formatting for parent prices
      const defaultWCSettings: WCSettings = {
        currency_symbol: 'Ft',
        currency_position: 'right_space',
        price_decimals: 0,
        price_decimal_separator: ',',
        price_thousand_separator: ' ',
        weight_unit: 'kg',
        dimension_unit: 'cm',
      };
      const wcSet = wcSettings || defaultWCSettings;
      
      // Parent row with aggregated data
      rows.push({
        id: parent.id,
        type: 'parent',
        isParent: true,
        expanded: expandedParents.has(parent.id),
        parent_name: parent.name,  // ✅ Map 'name' to 'parent_name' for AG Grid
        image_url: parent.image_url,
        variation_count: parent.variation_count,
        // Aggregated fields - RAW numbers, formatting in columnDefinitions
        price: formatPriceRange(minPrice, maxPrice, wcSet),
        regular_price: regularPrices.length === 0 ? '' : formatPriceRange(minRegularPrice, maxRegularPrice, wcSet),
        sale_price: salePrices.length === 0 ? '' : formatPriceRange(minSalePrice, maxSalePrice, wcSet),
        stock_quantity: totalStock,
        sku: '', // Parent has no SKU
        stock_status: totalStock > 0 ? 'instock' : 'outofstock',
        attributes: {}, // No attributes for parent row
      });

      // Variation rows (if expanded)
      if (expandedParents.has(parent.id)) {
        parent.variations.forEach((variation: any) => {
          rows.push({
            ...variation,
            type: 'variation',
            isParent: false,
            parentId: parent.id,
            // Keep matched flag from backend
          });
        });
      }
    });

    return rows;
  }, [data, viewMode, expandedParents]);

  // 🎯 Get WooCommerce settings from API
  const wcSettings = data?.data?.wc_settings;
  
  const tableRows = useMemo(() => buildGroupedRows(wcSettings), [buildGroupedRows, wcSettings]);

  // Toggle parent expand/collapse
  const toggleParentExpand = useCallback((parentId: number) => {
    setExpandedParents(prev => {
      const newSet = new Set(prev);
      if (newSet.has(parentId)) {
        newSet.delete(parentId);
      } else {
        newSet.add(parentId);
      }
      return newSet;
    });
  }, []);

  // Expand all parents
  const handleExpandAll = useCallback(() => {
    if (!data || viewMode !== 'grouped' || !data.data.parents) return;
    
    const allParentIds = new Set<number>(
      data.data.parents.map((parent: any) => parent.id)
    );
    setExpandedParents(allParentIds);
  }, [data, viewMode]);

  // Collapse all parents
  const handleCollapseAll = useCallback(() => {
    setExpandedParents(new Set());
  }, []);

  // 🔥 STEP 1: Detect checkedSearch + expand parents (NO selection yet!)
  useEffect(() => {
    console.log('[CheckedSearch Step 1] Expand useEffect triggered:', {
      checkedSearch: filters.checkedSearch,
      hasData: !!data,
      viewMode,
      dataParents: data?.data?.parents?.length || 0,
      hasAttributeFilter: filters.attributes?.length > 0
    });
    
    if (!filters.checkedSearch || !data || viewMode !== 'grouped') {
      console.log('[CheckedSearch Step 1] Early return - conditions not met');
      // Clear pending selection if checkbox unchecked
      if (!filters.checkedSearch) {
        pendingSelection.current = [];
      }
      return;
    }

    // Grouped mode: check data.data.parents
    if (!data.data.parents) {
      console.log('[CheckedSearch Step 1] No parents data');
      return;
    }

    const newExpandedParents = new Set<number>();
    const newSelectedIds: number[] = [];

    console.log('[CheckedSearch Step 1] DEBUGGING - First 3 parents:', 
      data.data.parents.slice(0, 3).map((p: any) => ({
        id: p.id,
        name: p.name,
        has_matches: p.has_matches,
        variation_count: p.variations?.length
      }))
    );

    // ✅ If NO attribute filter: select ALL variations
    const hasAttributeFilter = filters.attributes && filters.attributes.length > 0;
    
    console.log('[CheckedSearch Step 1] Filter check:', {
      hasAttributeFilter,
      filterAttributes: filters.attributes,
      totalParents: data.data.parents.length
    });
    
    if (!hasAttributeFilter) {
      console.log('[CheckedSearch Step 1] NO ATTRIBUTE FILTER - selecting ALL variations');
      data.data.parents.forEach((parent: any) => {
        // Auto-expand ALL parents
        newExpandedParents.add(parent.id);
        
        // Collect ALL variations
        parent.variations.forEach((variation: any) => {
          newSelectedIds.push(variation.id);
        });
      });
    } else {
      // ✅ With attribute filter: only select matched variations
      console.log('[CheckedSearch Step 1] WITH ATTRIBUTE FILTER - selecting matched only');
      data.data.parents.forEach((parent: any) => {
        if (parent.has_matches) {
          console.log('[CheckedSearch Step 1] Parent with matches:', parent.id, parent.name);
          // Auto-expand parent
          newExpandedParents.add(parent.id);

          // Collect matched variations
          parent.variations.forEach((variation: any) => {
            if (variation.matched) {
              console.log('[CheckedSearch Step 1] Matched variation:', variation.id);
              newSelectedIds.push(variation.id);
            }
          });
        }
      });
    }

    console.log('[CheckedSearch Step 1] Results:', {
      expandedParents: Array.from(newExpandedParents),
      selectedIds: newSelectedIds
    });

    // Save pending selection for STEP 2
    pendingSelection.current = newSelectedIds;
    
    // Expand parents → triggers re-render → AG Grid will have new rows
    setExpandedParents(newExpandedParents);
  }, [filters.checkedSearch, filters.attributes, data, viewMode]);

  // 🔥 STEP 2: After expand, select the nodes (when they exist in AG Grid!)
  useEffect(() => {
    // 🚨 CRITICAL: UNLOCK flag if checkedSearch is unchecked!
    if (!filters.checkedSearch) {
      console.log('[CheckedSearch Step 2] CheckedSearch disabled - UNLOCKING flag');
      isApplyingCheckedSearch.current = false;
      pendingSelection.current = [];
      return;
    }
    
    // Only run if we have pending selections
    if (pendingSelection.current.length === 0) {
      return;
    }

    const selectedIds = pendingSelection.current;
    
    console.log('[CheckedSearch Step 2] Selection useEffect triggered:', {
      expandedParentsCount: expandedParents.size,
      pendingSelectionCount: selectedIds.length
    });

    // Notify parent component
    if (onSelectionChange) {
      console.log('[CheckedSearch Step 2] Calling onSelectionChange with:', selectedIds);
      onSelectionChange(selectedIds);
    }
    
    // 🎯 USE ONMODELUPDATED EVENT (AG Grid lifecycle event after rows rendered)
    const gridApi = gridRef.current?.api;
    if (!gridApi) return;

    const handleModelUpdated = () => {
      console.log('[CheckedSearch Step 2] onModelUpdated fired - selecting nodes...');
      
      // 🔥 SET FLAG BEFORE ANY SELECTION (prevent onRowSelected from interfering)
      isApplyingCheckedSearch.current = true;
      console.log('[CheckedSearch Step 2] FLAG SET TO TRUE - onRowSelected should be blocked');
      
      let selectedCount = 0;
      const nodesToSelect: any[] = [];
      const parentIdsToSelect = new Set<number>();
      
      // First pass: collect variation nodes to select + track their parents
      gridApi.forEachNode(node => {
        if (node.data.type === 'variation' && selectedIds.includes(node.data.id)) {
          console.log('[CheckedSearch Step 2] Found variation to select:', node.data.id);
          nodesToSelect.push(node);
          parentIdsToSelect.add(node.data.parent_id); // Track parent ID
          selectedCount++;
        }
      });
      
      console.log('[CheckedSearch Step 2] Found nodes:', selectedCount, 'Parents:', parentIdsToSelect.size);
      
      // Second pass: deselect all first (clean slate)
      gridApi.deselectAll();
      
      // Third pass: select all matched variation nodes
      nodesToSelect.forEach(node => {
        console.log('[CheckedSearch Step 2] Calling setSelected for variation:', node.data.id);
        node.setSelected(true, false); // Don't clear other selections
      });
      
      // 🔥 Fourth pass: select parent nodes whose children are selected
      gridApi.forEachNode(node => {
        if (node.data.type === 'parent' && parentIdsToSelect.has(node.data.id)) {
          console.log('[CheckedSearch Step 2] Calling setSelected for parent:', node.data.id);
          node.setSelected(true, false); // Don't clear other selections
        }
      });
      
      console.log('[CheckedSearch Step 2] All setSelected calls completed');
      
      // 🔥 Check if selections actually happened
      const actualSelectedNodes = gridApi.getSelectedNodes();
      console.log('[CheckedSearch Step 2] Actually selected nodes:', actualSelectedNodes.length);
      
      // Unlock after 500ms (increased from 200ms)
      setTimeout(() => {
        isApplyingCheckedSearch.current = false;
        console.log('[CheckedSearch Step 2] FLAG UNLOCKED');
      }, 500);
      
      // Clear pending after successful selection
      pendingSelection.current = [];
      
      // Remove listener after first execution
      gridApi.removeEventListener('modelUpdated', handleModelUpdated);
    };

    // Add AG Grid lifecycle event listener
    gridApi.addEventListener('modelUpdated', handleModelUpdated);

    return () => {
      // Cleanup: remove listener if component unmounts
      gridApi.removeEventListener('modelUpdated', handleModelUpdated);
    };
  }, [expandedParents, filters.checkedSearch, onSelectionChange]);

  // Helper: Get preview for specific variation and field
  const getPreview = (variationId: number, field: string) => {
    const preview = previewData[variationId];
    if (!preview) return null;
    return preview.find((change) => change.field === field);
  };

  // Toggle parent expand/collapse

  // Column definitions - FÜGGNEK a previewData-tól!
  const columns = useMemo<ColDef[]>(() => {
    console.log('[VariationsTable] Creating columns with preview:', previewData);
    
    const baseColumns: ColDef[] = [];

    // 🔥 DINAMIKUS oszlopgenerálás a columnConfig alapján!
    const enabledColumns = getEnabledColumns(columnConfig);
    console.log('[VariationsTable] Enabled columns:', enabledColumns.map(c => c.id));
    
    // 🎯 Get WooCommerce settings from API response
    const wcSettings = data?.data?.wc_settings;
    const taxClassOptions = data?.data?.tax_class_options;
    console.log('[VariationsTable] WooCommerce settings from API:', wcSettings);
    console.log('[VariationsTable] Tax class options from API:', taxClassOptions);
    
    enabledColumns.forEach((colDef) => {
      const colId = colDef.id as ColumnId;
      const agGridCol = getColumnDefinition(
        colId,
        t,
        colDef.width,
        getPreview,
        setSalePriceEdit,
        toggleParentExpand,
        taxClassOptions, // 🎯 Pass tax classes to column definition
        wcSettings // 🎯 Pass WooCommerce settings (currency, units, formatting)
      );
      
      // ID oszlophoz checkbox selection + pinned left
      if (colId === 'id') {
        agGridCol.checkboxSelection = true; // ✅ MINDKETTŐ kap checkbox-ot (parent + variation)
        agGridCol.headerCheckboxSelection = viewMode === 'flat';
        agGridCol.pinned = 'left';
      }
      
      baseColumns.push(agGridCol);
    });

    return baseColumns;
  }, [t, previewData, viewMode, toggleParentExpand, columnConfig, data]); // 🎯 Add data dependency for tax_class_options


  // Cell value changed (auto-save with debounce)
  const onCellValueChanged = useCallback(async (params: any) => {
    const { id } = params.data;
    const field = params.column.getColId();
    const newValue = params.newValue;
    const oldValue = params.oldValue;
    
    // Skip if value unchanged
    if (newValue === oldValue) return;
    
    // 🔍 DEBUG: Log all changes
    console.log('[onCellValueChanged]', {
      field,
      id,
      oldValue,
      newValue,
      type: typeof newValue,
    });
    
    // ⚠️ SPECIAL CASE: stock_status change requires manage_stock check
    if (field === 'stock_status') {
      // 🔥 Skip if we're reverting (prevent infinite loop)
      if (isRevertingStockStatus.current) {
        isRevertingStockStatus.current = false;
        return;
      }
      
      const manageStock = params.data.manage_stock;
      
      if (manageStock) {
        // Set flag BEFORE reverting
        isRevertingStockStatus.current = true;
        
        // Revert immediately (AG Grid already changed the value)
        params.node.setDataValue(field, oldValue);
        
        // Show modal warning
        setStockStatusChange({
          variationId: id,
          currentStatus: oldValue,
          newStatus: newValue,
          oldValue: oldValue,
        });
        return;
      }
    }
    
    try {
      // Optimistic update already happened via AG Grid
      await updateMutation.mutateAsync({
        id,
        data: { [field]: newValue },
      });
      
      toast.success(t('saved'));
    } catch (error) {
      toast.error(t('save_error'));
      // Revert on error
      params.node.setDataValue(field, oldValue);
    }
  }, [updateMutation, t]);

  // Handle stock status modal confirmation
  const handleStockStatusConfirm = useCallback(async () => {
    if (!stockStatusChange) return;
    
    const { variationId, newStatus } = stockStatusChange;
    
    try {
      // 1. Disable manage_stock
      // 2. Set new stock_status
      await updateMutation.mutateAsync({
        id: variationId,
        data: { 
          manage_stock: false,
          stock_status: newStatus as 'instock' | 'outofstock' | 'onbackorder',
        },
      });
      
      // Update AG Grid node WITHOUT triggering onCellValueChanged
      const gridApi = gridRef.current?.api;
      if (gridApi) {
        gridApi.forEachNode((node) => {
          if (node.data.id === variationId) {
            // 🔥 Update data directly (no events triggered)
            node.data.manage_stock = false;
            node.data.stock_status = newStatus;
            // Force row refresh to update UI
            gridApi.refreshCells({ rowNodes: [node], force: true });
          }
        });
      }
      
      toast.success(t('saved'));
      setStockStatusChange(null);
    } catch (error) {
      toast.error(t('save_error'));
      setStockStatusChange(null);
    }
  }, [stockStatusChange, updateMutation, t]);

  const handleStockStatusCancel = useCallback(() => {
    setStockStatusChange(null);
  }, []);

  // Selection changed - Simple: only variations are selectable
    // Selection changed - Parent checkbox selects all children, child checkbox only itself
  const onSelectionChanged = useCallback(() => {
    if (!gridRef.current?.api) return;
    
    const gridApi = gridRef.current.api;
    const selectedNodes = gridApi.getSelectedNodes();
    
    // Csak a variation ID-ket küldjük vissza (parent sorok nem számítanak)
    const variationIds = selectedNodes
      .filter(node => {
        if (viewMode === 'flat') return true;
        return node.data.type === 'variation';
      })
      .map(node => node.data.id);
    
    onSelectionChange?.(variationIds);
  }, [onSelectionChange, viewMode]);

  // Checkbox kattintás kezelése - PARENT row-nál expandálás + child-ok propagálása
  const onRowSelected = useCallback(
    (event: any) => {
      // 🚨 NE fusson le, ha a checkedSearch állítja be a selection-t
      console.log('[onRowSelected] Triggered for:', event.node.data.type, event.node.data.id, 'Flag:', isApplyingCheckedSearch.current);
      if (isApplyingCheckedSearch.current) {
        console.log('[onRowSelected] BLOCKED by flag');
        return;
      }
      
      if (viewMode !== 'grouped') return;
      if (event.node.data.type !== 'parent') return;
      
      const gridApi = gridRef.current?.api;
      if (!gridApi) return;
      
      // Parent node jelenlegi állapota (már megváltozott a kattintásra)
      const isNowSelected = event.node.isSelected();
      const parentId = event.node.data.id;
      const wasExpanded = expandedParents.has(parentId);
      
      console.log('[onRowSelected] Parent checkbox clicked:', {
        parentId,
        isNowSelected,
        wasExpanded
      });
      
      // 🎯 Ha a parent még nincs expandálva ÉS most be lett pipálva
      if (!wasExpanded && isNowSelected) {
        console.log('[onRowSelected] Parent collapsed -> expanding + selecting children');
        
        // 1. Flag beállítása (race condition védelem)
        isExpandingForSelection.current = true;
        
        // 2. Expandáljuk a parentet (ez újra-rendereli a táblát child-okkal)
        setExpandedParents(prev => {
          const newSet = new Set(prev);
          newSet.add(parentId);
          return newSet;
        });
        
        // 3. Várunk egy frame-et amíg az új child row-ok megjelennek az AG Grid-ben
        requestAnimationFrame(() => {
          console.log('[onRowSelected] After expand, selecting children');
          
          // 4. getRowId prop miatt a parent selection automatikusan megmarad!
          // Csak a child-okat kell bepipálni (ezek új row-ok)
          gridApi.forEachNode((node) => {
            if (node.data.type === 'variation' && node.data.parent_id === parentId) {
              node.setSelected(true);
            }
          });
          
          // 5. Flag reset
          isExpandingForSelection.current = false;
        });
      } else if (!isExpandingForSelection.current) {
        // Ha már expanded volt VAGY kipipa, akkor azonnal szinkronizálhatjuk a child-okat
        // Flag check: ne fussunk le ha még folyamatban van az expand
        console.log('[onRowSelected] Syncing children immediately');
        
        gridApi.forEachNode((node) => {
          if (node.data.type === 'variation' && node.data.parent_id === parentId) {
            node.setSelected(isNowSelected);
          }
        });
      }
    },
    [viewMode, expandedParents]
  );

  // Grid ready
  const onGridReady = useCallback(() => {
    // Grid initialization
  }, []);

  // Handle sale price + dates save
  const handleSalePriceSave = async (price: string, dateFrom: string, dateTo: string) => {
    console.log('[handleSalePriceSave] CALLED with:', { price, dateFrom, dateTo, salePriceEdit });
    
    if (!salePriceEdit) {
      console.error('[handleSalePriceSave] NO salePriceEdit state!');
      return;
    }
    
    const variationId = salePriceEdit.variationId;
    console.log('[handleSalePriceSave] Variation ID:', variationId);
    
    // Close dropdown IMMEDIATELY (before async operation)
    setSalePriceEdit(null);
    
    try {
      const updateData: any = {
        sale_price: price || '',
      };
      
      // Add dates if provided
      if (dateFrom) {
        updateData.date_on_sale_from = dateFrom;
      }
      if (dateTo) {
        updateData.date_on_sale_to = dateTo;
      }
      
      console.log('[handleSalePriceSave] Calling API with:', updateData);
      
      // ✅ CRITICAL: This updates BOTH backend AND TanStack Query cache
      // The cache update triggers AG Grid re-render automatically!
      const result = await updateMutation.mutateAsync({
        id: variationId,
        data: updateData,
      });
      
      console.log('[handleSalePriceSave] API response:', result);
      console.log('[handleSalePriceSave] API call success, cache should be updated by onSuccess callback');
      
      toast.success(t('saved'));
      
      // ✅ Restore focus and scroll position AFTER cache update completes
      // Wait for React re-render cycle to complete
      setTimeout(() => {
        if (!gridRef.current?.api) return;
        
        const rowNode = gridRef.current.api.getRowNode(String(variationId));
        if (rowNode && rowNode.rowIndex !== null) {
          console.log('[handleSalePriceSave] Ensuring row visible at:', rowNode.rowIndex);
          
          // Only maintain scroll position - no focus change (modal already handles it)
          gridRef.current.api.ensureIndexVisible(rowNode.rowIndex, 'middle');
        }
      }, 200); // Increased timeout for cache update + re-render
    } catch (error) {
      console.error('[VariationsTable] Sale price save error:', error);
      toast.error(t('save_error'));
    }
  };

  // Error state
  if (error) {
    return (
      <div className="bg-white border border-gray-200 overflow-hidden">
        <FilterBar 
          onFilterChange={handleFilterChange}
          isLoading={false}
        />
        <div className="flex items-center justify-center h-96">
          <div className="text-red-500">{t('error')}: {error.message}</div>
        </div>
      </div>
    );
  }

  return (
    <div className="bg-white border border-gray-200 overflow-hidden">
      {/* Filter Bar */}
      <FilterBar 
        onFilterChange={handleFilterChange}
        isLoading={isFetching}
      />
      
      {/* Toolbar */}
      <Toolbar
        viewMode={viewMode}
        onViewModeChange={setViewMode}
        expandedCount={expandedParents.size}
        totalParents={data?.data.parents?.length || 0}
        onExpandAll={handleExpandAll}
        onCollapseAll={handleCollapseAll}
        checkedSearch={filters.checkedSearch}
        onCheckedSearchChange={handleCheckedSearchChange}
        hasAttributeFilter={filters.attributes.length > 0}
        onColumnConfig={() => setShowColumnConfig(true)}
      />
      
      {/* AG Grid Table - Native Loading Overlay */}
      <div className="relative">
        <div className="ag-theme-alpine" style={{ height: 'calc(100vh - 320px)', width: '100%' }}>
          <AgGridReact
          ref={gridRef}
          columnDefs={columns}
          rowData={isLoading && !data ? undefined : (viewMode === 'grouped' ? tableRows : (data?.data.variations || []))}
          getRowId={(params) => {
            // Stabil row ID-k: AG Grid megőrzi a selection state-et rowData változáskor
            const prefix = params.data.type === 'parent' ? 'parent-' : 'var-';
            return prefix + params.data.id;
          }}
          rowSelection="multiple"
          onCellValueChanged={onCellValueChanged}
          onSelectionChanged={onSelectionChanged}
          onRowSelected={onRowSelected}
          onGridReady={onGridReady}
          enableCellTextSelection={true}
          suppressRowClickSelection={true}
          animateRows={true}
          rowHeight={46}
          headerHeight={32}
          loading={isLoading}
          overlayLoadingTemplate={`<div style="display: flex; flex-direction: column; align-items: center; gap: 12px; padding: 20px;"><div class="inline-block h-8 w-8 animate-spin rounded-full border-4 border-solid border-blue-600 border-r-transparent" role="status"></div><span style="font-size: 16px; font-weight: 600; color: #1f2937;">${t('loading_grid')}</span></div>`}
          overlayNoRowsTemplate={`<span class="ag-overlay-no-rows-center" style="font-size: 15px; color: #6b7280;">${t('no_rows')}</span>`}
          getRowClass={(params) => {
            // Yellow highlight for matched variations (Checked Search)
            if (params.data.matched && filters.checkedSearch) {
              return 'bg-yellow-100 hover:bg-yellow-200';
            }
            // Parent row styling (bold, gray background)
            if (params.data.type === 'parent') {
              return 'bg-gray-50 font-bold hover:bg-gray-100';
            }
            // Variation row indent
            if (params.data.type === 'variation') {
              return 'pl-8';
            }
            return '';
          }}
        />
        </div>
      </div>
      
      {/* Pagination info */}
      <div className="px-3 py-1.5 bg-gray-50 border-t border-gray-200">
        <div className="flex items-center justify-between text-sm">
          <span className="text-gray-600 font-medium">
            {viewMode === 'grouped' ? (
              <>
                {t('showing')} <span className="font-bold text-gray-900">{data?.data.total_parents || 0}</span> {t('products')} / <span className="font-bold text-gray-900">{tableRows.filter(r => r.type === 'variation').length || 0}</span> {t('variations')}
              </>
            ) : (
              <>
                {t('showing')} <span className="font-bold text-gray-900">{data?.data.variations?.length || 0}</span> / <span className="font-bold text-gray-900">{data?.data.total || 0}</span> {t('variations')}
              </>
            )}
          </span>
        </div>
      </div>
      
      {/* Inline Sale Price Editor Dropdown */}
      {salePriceEdit && (
        <InlineSalePriceEditor
          currentPrice={salePriceEdit.currentPrice}
          dateFrom={salePriceEdit.dateFrom}
          dateTo={salePriceEdit.dateTo}
          position={salePriceEdit.position}
          onSave={handleSalePriceSave}
          onCancel={() => setSalePriceEdit(null)}
        />
      )}
      
      {/* Stock Status Change Modal */}
      {stockStatusChange && (
        <StockStatusModal
          currentStatus={stockStatusChange.currentStatus}
          newStatus={stockStatusChange.newStatus}
          onConfirm={handleStockStatusConfirm}
          onCancel={handleStockStatusCancel}
        />
      )}
      
      {/* Column Configuration Modal */}
      {showColumnConfig && (
        <ColumnConfigModal
          columns={columnConfig}
          onSave={handleColumnConfigSave}
          onClose={() => setShowColumnConfig(false)}
        />
      )}
    </div>
  );
}
