/**
 * ValidationStep Zustand Store
 *
 * Single source of truth for all validation state.
 * Uses immer for immutable updates and subscribeWithSelector for efficient subscriptions.
 */

import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer';
import { subscribeWithSelector } from 'zustand/middleware';
import { enableMapSet } from 'immer';
import { v4 as uuidv4 } from 'uuid';

// Enable Map and Set support in Immer
enableMapSet();
import type {
  ValidationStore,
  ValidationState,
  RowData,
  CleanRowData,
  ValidationError,
  RowValidationStatus,
  UpcValidationStatus,
  Template,
  TemplateState,
  FilterState,
  InitPhase,
  AiValidationProgress,
  AiValidationResults,
  CopyDownState,
  DialogState,
  InlineAiValidationResult,
} from './types';
import type { Field, SelectOption } from '../../../types';
import { stripPriceFormatting } from '../utils/priceUtils';

// =============================================================================
// Initial State
// =============================================================================

const initialTemplateState: TemplateState = {
  selectedTemplateId: null,
  showSaveDialog: false,
  newTemplateName: '',
  newTemplateType: '',
};

const initialFilterState: FilterState = {
  searchText: '',
  showErrorsOnly: false,
  filterField: null,
  filterValue: null,
};

const initialCopyDownState: CopyDownState = {
  isActive: false,
  sourceRowIndex: null,
  sourceFieldKey: null,
  targetRowIndex: null,
};

// Fields that require UPC validation when changed via copy-down
const UPC_VALIDATION_FIELDS = ['supplier', 'upc', 'barcode'];

const initialDialogState: DialogState = {
  templateFormOpen: false,
  templateFormData: null,
  createCategoryOpen: false,
};

const getInitialState = (): ValidationState => ({
  // Core Data
  rows: [],
  originalRows: [],

  // Field Configuration
  fields: [],
  fieldOptionsLoaded: false,

  // Validation
  errors: new Map(),
  rowValidationStatus: new Map(),

  // Cell States
  validatingCells: new Set(),
  editingCells: new Set(),

  // UPC Validation
  upcStatus: new Map(),
  generatedItemNumbers: new Map(),
  upcCache: new Map(),
  initialUpcValidationDone: false,

  // Product Lines
  productLinesCache: new Map(),
  sublinesCache: new Map(),
  loadingProductLines: new Set(),
  loadingSublines: new Set(),

  // Templates
  templates: [],
  templatesLoading: false,
  templateState: { ...initialTemplateState },

  // Filters
  filters: { ...initialFilterState },

  // Row Selection
  selectedRows: new Set(),

  // Copy-Down Mode
  copyDownMode: { ...initialCopyDownState },
  pendingCopyDownValidation: null,
  pendingInlineAiValidation: null,

  // Dialogs
  dialogs: { ...initialDialogState },

  // Initialization
  initPhase: 'idle',
  mappingSignature: null,

  // AI Validation
  aiValidation: {
    isRunning: false,
    progress: null,
    results: null,
    revertedChanges: new Set(),
  },

  // Inline AI Validation (Groq)
  inlineAi: {
    suggestions: new Map(),
    validating: new Set(),
    autoValidated: new Set(),
  },

  // File
  file: null,

  // UI State
  cellPopoverClosedAt: 0,
});

// =============================================================================
// Store Creation
// =============================================================================

export const useValidationStore = create<ValidationStore>()(
  subscribeWithSelector(
    immer((set, get) => ({
      ...getInitialState(),

      // =========================================================================
      // Initialization
      // =========================================================================

      initialize: async (data: RowData[], fields: Field<string>[], file?: File) => {
        console.log('[ValidationStore] initialize() called with', data.length, 'rows');

        // First, get a fresh initial state to ensure clean slate
        const freshState = getInitialState();

        set((state) => {
          console.log('[ValidationStore] Inside set callback, current initPhase:', state.initPhase);

          // Apply fresh state first (clean slate)
          Object.assign(state, freshState);

          // Identify price fields to clean on ingestion (strips $, commas, whitespace)
          const priceFieldKeys = fields
            .filter((f) => f.fieldType.type === 'input' && 'price' in f.fieldType && f.fieldType.price)
            .map((f) => f.key);

          // Then set up with new data, cleaning price fields
          state.rows = data.map((row) => {
            const cleanedRow: RowData = {
              ...row,
              __index: row.__index || uuidv4(),
            };
            for (const key of priceFieldKeys) {
              if (typeof cleanedRow[key] === 'string' && cleanedRow[key] !== '') {
                cleanedRow[key] = stripPriceFormatting(cleanedRow[key] as string);
              }
            }
            return cleanedRow;
          });
          state.originalRows = JSON.parse(JSON.stringify(state.rows));
          // Cast to bypass immer's strict readonly type checking
          state.fields = fields as unknown as typeof state.fields;
          state.file = file || null;
          state.initPhase = 'loading-options';
          console.log('[ValidationStore] Set initPhase to loading-options');
        });
        console.log('[ValidationStore] initialize() complete, new initPhase:', get().initPhase);
      },

      setFields: (fields: Field<string>[]) => {
        set((state) => {
          // Cast to bypass immer's strict readonly type checking
          state.fields = fields as unknown as typeof state.fields;
        });
      },

      setFieldOptionsLoaded: (loaded: boolean) => {
        set((state) => {
          state.fieldOptionsLoaded = loaded;
        });
      },

      setMappingSignature: (signature) => {
        set((state) => {
          state.mappingSignature = signature;
        });
      },

      /**
       * Merge freshly-mapped rows into the existing (edited) rows when returning from
       * Match Columns. Aligns by __sourceRow so edits, selection, and __index are
       * preserved; only fields whose mapping changed are overwritten, and fields that
       * became unmapped are cleared. Rows deleted in Validation are not re-added.
       */
      reconcileMappedData: (freshRows: RowData[], changedFieldKeys: string[], clearedFieldKeys: string[]) => {
        if (changedFieldKeys.length === 0 && clearedFieldKeys.length === 0) return;

        set((state) => {
          // Price fields are stripped of $/commas on ingestion; mirror that here so
          // re-pulled values match how they were cleaned during initialize().
          const priceFieldKeys = new Set(
            state.fields
              .filter((f) => f.fieldType.type === 'input' && 'price' in f.fieldType && f.fieldType.price)
              .map((f) => f.key),
          );
          const cleanValue = (key: string, value: unknown) =>
            priceFieldKeys.has(key) && typeof value === 'string' && value !== ''
              ? stripPriceFormatting(value)
              : value;

          // Index fresh rows by their stable source-row id.
          const freshBySource = new Map<number, RowData>();
          for (const row of freshRows) {
            if (typeof row.__sourceRow === 'number') {
              freshBySource.set(row.__sourceRow, row);
            }
          }

          state.rows.forEach((row, idx) => {
            const fresh = typeof row.__sourceRow === 'number' ? freshBySource.get(row.__sourceRow) : undefined;

            // Overwrite changed fields from the freshly-mapped source row.
            if (fresh) {
              for (const key of changedFieldKeys) {
                const value = cleanValue(key, fresh[key]);
                row[key] = value;
                if (state.originalRows[idx]) {
                  state.originalRows[idx][key] = value;
                }
              }
            }

            // Clear fields that are no longer mapped.
            for (const key of clearedFieldKeys) {
              row[key] = undefined;
              if (state.originalRows[idx]) {
                state.originalRows[idx][key] = undefined;
              }
            }
          });
        });
      },

      // =========================================================================
      // Row Operations
      // =========================================================================

      updateCell: (rowIndex: number, field: string, value: unknown) => {
        set((state) => {
          if (state.rows[rowIndex]) {
            state.rows[rowIndex][field] = value;
          }
        });
      },

      updateRow: (rowIndex: number, updates: Partial<RowData>) => {
        set((state) => {
          if (state.rows[rowIndex]) {
            Object.assign(state.rows[rowIndex], updates);
          }
        });
      },

      deleteRows: (rowIndexes: number[]) => {
        set((state) => {
          // Collect row IDs to remove from selection before deleting
          const rowIdsToDelete = new Set<string>();
          rowIndexes.forEach((index) => {
            if (index >= 0 && index < state.rows.length) {
              const rowId = state.rows[index].__index;
              if (rowId) rowIdsToDelete.add(rowId);
            }
          });

          // Clear these rows from selectedRows
          rowIdsToDelete.forEach((rowId) => {
            state.selectedRows.delete(rowId);
          });

          // Sort descending to delete from end first (preserves indices)
          const sorted = [...rowIndexes].sort((a, b) => b - a);
          sorted.forEach((index) => {
            if (index >= 0 && index < state.rows.length) {
              state.rows.splice(index, 1);
              state.errors.delete(index);
              state.rowValidationStatus.delete(index);
              state.upcStatus.delete(index);
              state.generatedItemNumbers.delete(index);
            }
          });

          // Reindex remaining Maps after deletion
          // This is necessary because we use numeric indices as keys
          const reindexMap = <T>(map: Map<number, T>): Map<number, T> => {
            const entries = Array.from(map.entries())
              .filter(([idx]) => !rowIndexes.includes(idx))
              .sort(([a], [b]) => a - b);

            const newMap = new Map<number, T>();
            let newIndex = 0;
            entries.forEach(([, value]) => {
              newMap.set(newIndex++, value);
            });
            return newMap;
          };

          state.errors = reindexMap(state.errors) as typeof state.errors;
          state.rowValidationStatus = reindexMap(state.rowValidationStatus);
          state.upcStatus = reindexMap(state.upcStatus);
          state.generatedItemNumbers = reindexMap(state.generatedItemNumbers);
        });
      },

      addRow: (rowData?: Partial<RowData>) => {
        set((state) => {
          const newRow: RowData = {
            __index: uuidv4(),
            ...rowData,
          };
          state.rows.push(newRow);
        });
      },

      copyDown: (fromRowIndex: number, fieldKey: string, toRowIndex?: number) => {
        set((state) => {
          const sourceRow = state.rows[fromRowIndex];
          const sourceValue = sourceRow?.[fieldKey];
          if (sourceValue === undefined) return;

          const endIndex = toRowIndex ?? state.rows.length - 1;
          const isInlineAiField = fieldKey === 'name' || fieldKey === 'description';

          // For inline AI fields, check if source was validated/dismissed
          // If so, we'll mark targets as autoValidated to skip re-validation
          let sourceIsDismissed = false;
          if (isInlineAiField && sourceRow?.__index) {
            const sourceSuggestion = state.inlineAi.suggestions.get(sourceRow.__index);
            sourceIsDismissed = sourceSuggestion?.dismissed?.[fieldKey as 'name' | 'description'] ?? false;
          }

          for (let i = fromRowIndex + 1; i <= endIndex; i++) {
            const targetRow = state.rows[i];
            if (targetRow) {
              targetRow[fieldKey] = sourceValue;

              // For name/description fields:
              // 1. Mark as autoValidated so blur won't re-validate
              // 2. Clear any existing suggestion for this field (value changed)
              // 3. Set dismissed state based on source (if source was dismissed, targets are also valid)
              if (isInlineAiField && targetRow.__index) {
                const field = fieldKey as 'name' | 'description';
                state.inlineAi.autoValidated.add(`${targetRow.__index}-${field}`);

                // Clear existing suggestion and set dismissed state
                const existing = state.inlineAi.suggestions.get(targetRow.__index) || {};
                state.inlineAi.suggestions.set(targetRow.__index, {
                  ...existing,
                  [field]: undefined, // Clear the suggestion for this field
                  dismissed: {
                    ...existing.dismissed,
                    [field]: sourceIsDismissed, // Copy dismissed state from source
                  },
                });
              }
            }
          }
        });
      },

      setRows: (rows: RowData[]) => {
        set((state) => {
          state.rows = rows;
        });
      },

      // =========================================================================
      // Validation
      // =========================================================================

      setError: (rowIndex: number, field: string, error: ValidationError | null) => {
        set((state) => {
          if (!state.errors.has(rowIndex)) {
            state.errors.set(rowIndex, {});
          }
          const rowErrors = state.errors.get(rowIndex)!;

          if (error === null) {
            delete rowErrors[field];
            if (Object.keys(rowErrors).length === 0) {
              state.errors.delete(rowIndex);
            }
          } else {
            rowErrors[field] = [error];
          }
        });
      },

      setErrors: (rowIndex: number, errors: Record<string, ValidationError[]>) => {
        set((state) => {
          if (Object.keys(errors).length === 0) {
            state.errors.delete(rowIndex);
          } else {
            state.errors.set(rowIndex, errors);
          }
        });
      },

      /**
       * PERFORMANCE: Batch set all errors and row statuses in a single store update.
       * This avoids the O(n) Immer Map/Set cloning that happens on every individual set() call.
       * Use this for bulk validation operations like validateAllRows.
       */
      setBulkValidationResults: (
        allErrors: Map<number, Record<string, ValidationError[]>>,
        allStatuses: Map<number, RowValidationStatus>
      ) => {
        set((state) => {
          // Replace entire errors map
          state.errors = allErrors as typeof state.errors;
          // Replace entire status map
          state.rowValidationStatus = allStatuses;
        });
      },

      clearRowErrors: (rowIndex: number) => {
        set((state) => {
          state.errors.delete(rowIndex);
        });
      },

      clearFieldError: (rowIndex: number, field: string) => {
        set((state) => {
          const rowErrors = state.errors.get(rowIndex);
          if (rowErrors) {
            delete rowErrors[field];
            if (Object.keys(rowErrors).length === 0) {
              state.errors.delete(rowIndex);
            }
          }
        });
      },

      setRowValidationStatus: (rowIndex: number, status: RowValidationStatus) => {
        set((state) => {
          state.rowValidationStatus.set(rowIndex, status);
        });
      },

      // =========================================================================
      // Cell States
      // =========================================================================

      startValidatingCell: (rowIndex: number, field: string) => {
        set((state) => {
          state.validatingCells.add(`${rowIndex}-${field}`);
        });
      },

      stopValidatingCell: (rowIndex: number, field: string) => {
        set((state) => {
          state.validatingCells.delete(`${rowIndex}-${field}`);
        });
      },

      startEditingCell: (rowIndex: number, field: string) => {
        set((state) => {
          state.editingCells.add(`${rowIndex}-${field}`);
        });
      },

      stopEditingCell: (rowIndex: number, field: string) => {
        set((state) => {
          state.editingCells.delete(`${rowIndex}-${field}`);
        });
      },

      // =========================================================================
      // UPC Validation
      // =========================================================================

      setUpcStatus: (rowIndex: number, status: UpcValidationStatus) => {
        set((state) => {
          state.upcStatus.set(rowIndex, status);
        });
      },

      setGeneratedItemNumber: (rowIndex: number, itemNumber: string) => {
        set((state) => {
          state.generatedItemNumbers.set(rowIndex, itemNumber);
          // Also update the row data
          if (state.rows[rowIndex]) {
            state.rows[rowIndex].item_number = itemNumber;
          }
          // Clear any validation errors for item_number since we just set a valid value
          const rowErrors = state.errors.get(rowIndex);
          if (rowErrors && rowErrors.item_number) {
            const { item_number: _, ...remainingErrors } = rowErrors;
            if (Object.keys(remainingErrors).length === 0) {
              state.errors.delete(rowIndex);
            } else {
              state.errors.set(rowIndex, remainingErrors);
            }
          }
        });
      },

      cacheUpcResult: (supplierId: string, upc: string, itemNumber: string) => {
        set((state) => {
          state.upcCache.set(`${supplierId}-${upc}`, itemNumber);
        });
      },

      getCachedItemNumber: (supplierId: string, upc: string) => {
        return get().upcCache.get(`${supplierId}-${upc}`);
      },

      setInitialUpcValidationDone: (done: boolean) => {
        set((state) => {
          state.initialUpcValidationDone = done;
        });
      },

      // =========================================================================
      // Product Lines
      // =========================================================================

      setProductLines: (companyId: string, lines: SelectOption[]) => {
        set((state) => {
          state.productLinesCache.set(companyId, lines);
        });
      },

      setSublines: (lineId: string, sublines: SelectOption[]) => {
        set((state) => {
          state.sublinesCache.set(lineId, sublines);
        });
      },

      setLoadingProductLines: (companyId: string, loading: boolean) => {
        set((state) => {
          if (loading) {
            state.loadingProductLines.add(companyId);
          } else {
            state.loadingProductLines.delete(companyId);
          }
        });
      },

      setLoadingSublines: (lineId: string, loading: boolean) => {
        set((state) => {
          if (loading) {
            state.loadingSublines.add(lineId);
          } else {
            state.loadingSublines.delete(lineId);
          }
        });
      },

      // =========================================================================
      // Templates
      // =========================================================================

      setTemplates: (templates: Template[]) => {
        set((state) => {
          state.templates = templates;
        });
      },

      setTemplatesLoading: (loading: boolean) => {
        set((state) => {
          state.templatesLoading = loading;
        });
      },

      setTemplateState: (updates: Partial<TemplateState>) => {
        set((state) => {
          Object.assign(state.templateState, updates);
        });
      },

      // =========================================================================
      // Filters
      // =========================================================================

      setSearchText: (text: string) => {
        set((state) => {
          state.filters.searchText = text;
        });
      },

      setShowErrorsOnly: (value: boolean) => {
        set((state) => {
          state.filters.showErrorsOnly = value;
        });
      },

      setFilters: (updates: Partial<FilterState>) => {
        set((state) => {
          Object.assign(state.filters, updates);
        });
      },

      // =========================================================================
      // Row Selection
      // =========================================================================

      setSelectedRows: (rows: Set<string>) => {
        set((state) => {
          state.selectedRows = rows;
        });
      },

      toggleRowSelection: (rowId: string) => {
        set((state) => {
          if (state.selectedRows.has(rowId)) {
            state.selectedRows.delete(rowId);
          } else {
            state.selectedRows.add(rowId);
          }
        });
      },

      selectAllRows: () => {
        set((state) => {
          state.selectedRows = new Set(state.rows.map((row: RowData) => row.__index));
        });
      },

      clearSelection: () => {
        set((state) => {
          state.selectedRows = new Set();
        });
      },

      // =========================================================================
      // Copy-Down Mode
      // =========================================================================

      setCopyDownMode: (mode: Partial<CopyDownState>) => {
        set((state) => {
          Object.assign(state.copyDownMode, mode);
        });
      },

      startCopyDown: (rowIndex: number, fieldKey: string) => {
        set((state) => {
          state.copyDownMode = {
            isActive: true,
            sourceRowIndex: rowIndex,
            sourceFieldKey: fieldKey,
            targetRowIndex: null,
          };
        });
      },

      cancelCopyDown: () => {
        set((state) => {
          state.copyDownMode = { ...initialCopyDownState };
        });
      },

      completeCopyDown: (targetRowIndex: number) => {
        const { copyDownMode } = get();
        if (!copyDownMode.isActive || copyDownMode.sourceRowIndex === null || !copyDownMode.sourceFieldKey) {
          return;
        }

        const fieldKey = copyDownMode.sourceFieldKey;
        const sourceRowIndex = copyDownMode.sourceRowIndex;

        // First, perform the copy operation
        set((state) => {
          const sourceValue = state.rows[sourceRowIndex]?.[fieldKey];
          if (sourceValue === undefined) return;

          // Clone value for arrays/objects to prevent reference sharing
          const cloneValue = (val: unknown): unknown => {
            if (Array.isArray(val)) return [...val];
            if (val && typeof val === 'object') return { ...val };
            return val;
          };

          // Check if value is non-empty (for clearing required errors)
          const hasValue = sourceValue !== null && sourceValue !== '' &&
            !(Array.isArray(sourceValue) && sourceValue.length === 0);

          // Track affected rows for UPC validation
          const affectedRows: number[] = [];

          for (let i = sourceRowIndex + 1; i <= targetRowIndex; i++) {
            if (state.rows[i]) {
              state.rows[i][fieldKey] = cloneValue(sourceValue);
              affectedRows.push(i);

              // Clear validation errors for this field if value is non-empty
              if (hasValue) {
                const rowErrors = state.errors.get(i);
                if (rowErrors && rowErrors[fieldKey]) {
                  // Remove errors for this field
                  const { [fieldKey]: _, ...remainingErrors } = rowErrors;
                  if (Object.keys(remainingErrors).length === 0) {
                    state.errors.delete(i);
                  } else {
                    state.errors.set(i, remainingErrors);
                  }
                }
              }
            }
          }

          // Reset copy-down mode
          state.copyDownMode = { ...initialCopyDownState };

          // If this field affects UPC validation, store the affected rows
          // so a hook can trigger validation using the existing validateUpc function
          if (UPC_VALIDATION_FIELDS.includes(fieldKey) && affectedRows.length > 0) {
            state.pendingCopyDownValidation = {
              fieldKey,
              affectedRows,
            };
          }

          // If line is being copied, check which rows now have sufficient context
          // for inline AI validation (company + line + name/description)
          if (fieldKey === 'line' && affectedRows.length > 0) {
            const nameRows: number[] = [];
            const descriptionRows: number[] = [];

            for (const rowIdx of affectedRows) {
              const row = state.rows[rowIdx];
              if (!row?.__index) continue;

              // Check if row has company + line (just set) + name
              const hasNameContext = row.company && sourceValue && row.name &&
                typeof row.name === 'string' && row.name.trim();

              if (hasNameContext) {
                // Check if name hasn't been dismissed
                const suggestion = state.inlineAi.suggestions.get(row.__index);
                const nameIsDismissed = suggestion?.dismissed?.name;
                if (!nameIsDismissed) {
                  nameRows.push(rowIdx);
                }

                // Check if description also has sufficient context
                const hasDescContext = row.description &&
                  typeof row.description === 'string' && row.description.trim();
                const descIsDismissed = suggestion?.dismissed?.description;
                if (hasDescContext && !descIsDismissed) {
                  descriptionRows.push(rowIdx);
                }
              }
            }

            if (nameRows.length > 0 || descriptionRows.length > 0) {
              state.pendingInlineAiValidation = { nameRows, descriptionRows };
            }
          }
        });
      },

      setTargetRowHover: (rowIndex: number | null) => {
        set((state) => {
          if (state.copyDownMode.isActive) {
            state.copyDownMode.targetRowIndex = rowIndex;
          }
        });
      },

      clearPendingCopyDownValidation: () => {
        set((state) => {
          state.pendingCopyDownValidation = null;
        });
      },

      clearPendingInlineAiValidation: () => {
        set((state) => {
          state.pendingInlineAiValidation = null;
        });
      },

      // =========================================================================
      // Dialogs
      // =========================================================================

      setDialogs: (updates: Partial<DialogState>) => {
        set((state) => {
          Object.assign(state.dialogs, updates);
        });
      },

      openTemplateForm: (initialData: Record<string, unknown>) => {
        set((state) => {
          state.dialogs.templateFormOpen = true;
          state.dialogs.templateFormData = initialData;
        });
      },

      closeTemplateForm: () => {
        set((state) => {
          state.dialogs.templateFormOpen = false;
          state.dialogs.templateFormData = null;
        });
      },

      // =========================================================================
      // Initialization Phase
      // =========================================================================

      setInitPhase: (phase: InitPhase) => {
        set((state) => {
          state.initPhase = phase;
        });
      },

      // =========================================================================
      // AI Validation
      // =========================================================================

      setAiValidationRunning: (running: boolean) => {
        set((state) => {
          state.aiValidation.isRunning = running;
        });
      },

      setAiValidationProgress: (
        progressOrUpdater: AiValidationProgress | null | ((prev: AiValidationProgress | null) => AiValidationProgress | null)
      ) => {
        set((state) => {
          if (typeof progressOrUpdater === 'function') {
            // Support callback pattern for updates based on previous state
            state.aiValidation.progress = progressOrUpdater(state.aiValidation.progress);
          } else {
            state.aiValidation.progress = progressOrUpdater;
          }
        });
      },

      setAiValidationResults: (results: AiValidationResults | null) => {
        set((state) => {
          state.aiValidation.results = results;
        });
      },

      revertAiChange: (productIndex: number, fieldKey: string) => {
        set((state) => {
          const key = `${productIndex}:${fieldKey}`;
          const row = state.rows[productIndex];

          if (row && row.__original && fieldKey in row.__original) {
            // Revert to original value
            row[fieldKey] = row.__original[fieldKey];
            // Mark as reverted
            state.aiValidation.revertedChanges.add(key);
            // Clear the change marker
            if (row.__changes) {
              delete row.__changes[fieldKey];
            }
          }
        });
      },

      acceptAiChange: (productIndex: number, fieldKey: string) => {
        set((state) => {
          const key = `${productIndex}:${fieldKey}`;
          const row = state.rows[productIndex];

          if (row && row.__corrected && fieldKey in row.__corrected) {
            // Re-apply the corrected value
            row[fieldKey] = row.__corrected[fieldKey];
            // Remove from reverted set
            state.aiValidation.revertedChanges.delete(key);
            // Re-mark as changed
            if (!row.__changes) {
              row.__changes = {};
            }
            row.__changes[fieldKey] = true;
          }
        });
      },

      clearAiValidation: () => {
        set((state) => {
          state.aiValidation = {
            isRunning: false,
            progress: null,
            results: null,
            revertedChanges: new Set(),
          };
        });
      },

      storeOriginalValues: () => {
        set((state) => {
          state.rows.forEach((row: RowData) => {
            row.__original = { ...row };
          });
        });
      },

      // =========================================================================
      // Inline AI Validation (Groq)
      // =========================================================================

      setInlineAiSuggestion: (productIndex: string, field: 'name' | 'description', result: InlineAiValidationResult) => {
        // Debug: Log what we're setting
        console.log('[Store] setInlineAiSuggestion called:', {
          productIndex,
          field,
          result,
        });

        set((state) => {
          const existing = state.inlineAi.suggestions.get(productIndex) || {};
          const newSuggestion = {
            ...existing,
            [field]: result,
            dismissed: {
              ...existing.dismissed,
              [field]: false, // Reset dismissed state when new suggestion arrives
            },
          };
          state.inlineAi.suggestions.set(productIndex, newSuggestion);
          state.inlineAi.validating.delete(`${productIndex}-${field}`);

          // Debug: Log what's in the Map now
          console.log('[Store] After set, suggestions Map has:', productIndex, state.inlineAi.suggestions.get(productIndex));
        });
      },

      dismissInlineAiSuggestion: (productIndex: string, field: 'name' | 'description') => {
        set((state) => {
          const existing = state.inlineAi.suggestions.get(productIndex);
          if (existing) {
            state.inlineAi.suggestions.set(productIndex, {
              ...existing,
              dismissed: {
                ...existing.dismissed,
                [field]: true,
              },
            });
          }
        });
      },

      acceptInlineAiSuggestion: (productIndex: string, field: 'name' | 'description') => {
        set((state) => {
          const suggestion = state.inlineAi.suggestions.get(productIndex)?.[field];
          if (suggestion?.suggestion) {
            // Find the row by __index and update the field
            const rowIndex = state.rows.findIndex((row: RowData) => row.__index === productIndex);
            if (rowIndex >= 0) {
              state.rows[rowIndex][field] = suggestion.suggestion;
            }
            // Mark as dismissed after accepting
            const existing = state.inlineAi.suggestions.get(productIndex);
            if (existing) {
              state.inlineAi.suggestions.set(productIndex, {
                ...existing,
                dismissed: {
                  ...existing.dismissed,
                  [field]: true,
                },
              });
            }
          }
        });
      },

      clearInlineAiSuggestion: (productIndex: string, field?: 'name' | 'description') => {
        set((state) => {
          if (field) {
            const existing = state.inlineAi.suggestions.get(productIndex);
            if (existing) {
              const { [field]: _, ...rest } = existing;
              if (Object.keys(rest).length === 0 || (Object.keys(rest).length === 1 && 'dismissed' in rest)) {
                state.inlineAi.suggestions.delete(productIndex);
              } else {
                state.inlineAi.suggestions.set(productIndex, rest);
              }
            }
          } else {
            state.inlineAi.suggestions.delete(productIndex);
          }
        });
      },

      setInlineAiValidating: (productIndex: string, validating: boolean) => {
        set((state) => {
          if (validating) {
            state.inlineAi.validating.add(productIndex);
          } else {
            state.inlineAi.validating.delete(productIndex);
          }
        });
      },

      markInlineAiAutoValidated: (productIndex: string, field: 'name' | 'description') => {
        set((state) => {
          state.inlineAi.autoValidated.add(`${productIndex}-${field}`);
        });
      },

      isInlineAiAutoValidated: (productIndex: string, field: 'name' | 'description') => {
        return get().inlineAi.autoValidated.has(`${productIndex}-${field}`);
      },

      // =========================================================================
      // Output
      // =========================================================================

      getCleanedData: (): CleanRowData[] => {
        const { rows } = get();
        // Price fields that should be formatted to 2 decimal places for API submission
        const priceFields = ['msrp', 'cost_each'];

        return rows.map((row) => {
          // eslint-disable-next-line @typescript-eslint/no-unused-vars
          const { __index, __template, __original, __corrected, __changes, __aiSupplemental, ...cleanRow } = row;

          // Format price fields to 2 decimal places for API submission
          // This ensures consistent precision while internal storage keeps full precision for calculations
          for (const field of priceFields) {
            const value = cleanRow[field];
            if (value !== undefined && value !== null && value !== '') {
              const num = parseFloat(String(value));
              if (!isNaN(num)) {
                cleanRow[field] = num.toFixed(2);
              }
            }
          }

          return cleanRow as CleanRowData;
        });
      },

      // =========================================================================
      // UI State
      // =========================================================================

      setCellPopoverClosed: () => {
        set((state) => {
          state.cellPopoverClosedAt = Date.now();
        });
      },

      // =========================================================================
      // Reset
      // =========================================================================

      reset: () => {
        console.log('[ValidationStore] reset() called');
        console.trace('[ValidationStore] reset trace');
        set(getInitialState());
      },
    }))
  )
);

// =============================================================================
// Store Selectors (for use outside React components)
// =============================================================================

export const getRows = () => useValidationStore.getState().rows;
export const getErrors = () => useValidationStore.getState().errors;
export const getFields = () => useValidationStore.getState().fields;
