/**
 * useTemplateManagement Hook
 *
 * Manages template loading, applying, and saving.
 * Templates provide pre-filled values that can be applied to rows.
 *
 * PERFORMANCE NOTE: This hook must NOT subscribe to the rows array!
 * Using useRows() or useSelectedRowIndices() causes re-render on EVERY cell
 * change. Instead, use getState() to read rows at action time.
 */

import { useCallback } from 'react';
import { apiFetch } from '@/utils/api';
import { useValidationStore } from '../store/validationStore';
import {
  useTemplates,
  useTemplatesLoading,
  useTemplateState,
  useFields,
} from '../store/selectors';
import { toast } from 'sonner';
import config from '@/config';
import type { Template, RowData } from '../store/types';

// Fields to exclude from template data
const TEMPLATE_EXCLUDE_FIELDS = [
  'id',
  '__index',
  '__meta',
  '__template',
  '__original',
  '__corrected',
  '__changes',
  '__aiSupplemental',
];

/**
 * Hook for template management operations
 */
export const useTemplateManagement = () => {
  // PERFORMANCE: Only subscribe to templates state, NOT rows!
  // Rows are read via getState() at action time
  const templates = useTemplates();
  const templatesLoading = useTemplatesLoading();
  const templateState = useTemplateState();
  const fields = useFields();

  // Store actions
  const setTemplates = useValidationStore((state) => state.setTemplates);
  const setTemplatesLoading = useValidationStore((state) => state.setTemplatesLoading);
  const setTemplateState = useValidationStore((state) => state.setTemplateState);

  /**
   * Load templates from API
   */
  const loadTemplates = useCallback(async () => {
    setTemplatesLoading(true);

    try {
      const response = await apiFetch(`${config.apiUrl}/templates`);
      if (!response.ok) throw new Error('Failed to fetch templates');

      const data = await response.json();
      const validTemplates = data.filter(
        (t: Template) => t && typeof t === 'object' && t.id && t.company && t.product_type
      );

      setTemplates(validTemplates);
    } catch (error) {
      console.error('Error fetching templates:', error);
      toast.error('Failed to load templates');
    } finally {
      setTemplatesLoading(false);
    }
  }, [setTemplates, setTemplatesLoading]);

  /**
   * Apply template to specific rows
   * PERFORMANCE: Uses getState() to read rows at action time, avoiding subscriptions
   */
  const applyTemplate = useCallback(
    async (templateId: string, rowIndexes: number[]) => {
      const template = templates.find((t) => t.id.toString() === templateId);
      if (!template) {
        toast.error('Template not found');
        return;
      }

      // Get current state at action time
      const {
        rows,
        updateRow,
        clearRowErrors,
        setRowValidationStatus,
      } = useValidationStore.getState();

      // Validate row indexes
      const validIndexes = rowIndexes.filter(
        (index) => index >= 0 && index < rows.length && Number.isInteger(index)
      );

      if (validIndexes.length === 0) {
        toast.error('No valid rows to update');
        return;
      }

      // Extract template fields, excluding those with empty/null/undefined values
      // This preserves existing row values when template has no value for a field
      const templateFields = Object.entries(template).filter(
        ([key, value]) => {
          if (TEMPLATE_EXCLUDE_FIELDS.includes(key)) return false;
          // Skip empty values so existing row data is preserved
          if (value === null || value === undefined || value === '') return false;
          // Skip empty arrays
          if (Array.isArray(value) && value.length === 0) return false;
          return true;
        }
      );

      // Apply template to each row
      const rowsNeedingUpcValidation: { rowIndex: number; supplierId: string; upcValue: string }[] = [];

      for (const rowIndex of validIndexes) {
        // Build updates object
        const updates: Partial<RowData> = {
          __template: templateId,
        };

        for (const [key, value] of templateFields) {
          updates[key] = value;
        }

        // Apply updates
        updateRow(rowIndex, updates);

        // Clear validation errors (template values are presumed valid)
        clearRowErrors(rowIndex);
        setRowValidationStatus(rowIndex, 'validated');

        // Check if row needs UPC validation
        const row = rows[rowIndex];
        const hasUpc = updates.upc || row?.upc;
        const hasSupplier = updates.supplier || row?.supplier;
        if (hasUpc && hasSupplier) {
          rowsNeedingUpcValidation.push({
            rowIndex,
            supplierId: String(updates.supplier || row?.supplier || ''),
            upcValue: String(updates.upc || row?.upc || ''),
          });
        }
      }

      // Show success toast
      if (validIndexes.length === 1) {
        toast.success('Template applied');
      } else {
        toast.success(`Template applied to ${validIndexes.length} rows`);
      }

      // Trigger UPC validation for affected rows in background
      // Note: We captured the values above to avoid re-reading stale state
      for (const { rowIndex, supplierId, upcValue } of rowsNeedingUpcValidation) {
        if (supplierId && upcValue) {
          // Don't await - let it run in background
          // UPC validation uses its own hooks which will update the store
          apiFetch(`/api/import/validate-upc/${supplierId}/${encodeURIComponent(upcValue)}`)
            .then((res) => res.json())
            .then((result) => {
              if (result.itemNumber) {
                const { updateCell, setUpcStatus } = useValidationStore.getState();
                updateCell(rowIndex, 'item_number', result.itemNumber);
                setUpcStatus(rowIndex, 'done');
              }
            })
            .catch(console.error);
        }
      }
    },
    [templates]
  );

  /**
   * Apply template to selected rows
   * PERFORMANCE: Gets selected row indices at action time via getState()
   */
  const applyTemplateToSelected = useCallback(
    (templateId: string) => {
      if (!templateId) return;

      setTemplateState({ selectedTemplateId: templateId });

      // Get selected row indices at action time
      const { rows, selectedRows } = useValidationStore.getState();
      const selectedRowIndices: number[] = [];
      rows.forEach((row, index) => {
        if (selectedRows.has(row.__index)) {
          selectedRowIndices.push(index);
        }
      });

      if (selectedRowIndices.length === 0) {
        toast.error('No rows selected');
        return;
      }

      applyTemplate(templateId, selectedRowIndices);
    },
    [applyTemplate, setTemplateState]
  );

  /**
   * Save a new template from a row
   * PERFORMANCE: Uses getState() to read rows at action time
   */
  const saveTemplate = useCallback(
    async (name: string, type: string, sourceRowIndex: number) => {
      // Get row data at action time
      const { rows, updateRow } = useValidationStore.getState();
      const row = rows[sourceRowIndex];
      if (!row) {
        toast.error('Invalid row selected');
        return;
      }

      // Extract data for template, excluding metadata
      const templateData: Record<string, unknown> = {};

      for (const [key, value] of Object.entries(row)) {
        if (TEMPLATE_EXCLUDE_FIELDS.includes(key)) continue;

        // Clean price values
        if (typeof value === 'string' && value.includes('$')) {
          templateData[key] = value.replace(/[$,\s]/g, '').trim();
        } else {
          templateData[key] = value;
        }
      }

      try {
        const response = await apiFetch(`${config.apiUrl}/templates`, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            ...templateData,
            company: name,
            product_type: type,
          }),
        });

        if (!response.ok) {
          const errorData = await response.json();
          throw new Error(errorData.error || errorData.details || 'Failed to save template');
        }

        const newTemplate = await response.json();

        // Add to templates list
        setTemplates([...templates, newTemplate]);

        // Mark row as using this template
        updateRow(sourceRowIndex, { __template: newTemplate.id.toString() });

        toast.success(`Template "${name}" saved successfully`);

        // Reset dialog state
        setTemplateState({
          showSaveDialog: false,
          newTemplateName: '',
          newTemplateType: '',
        });
      } catch (error) {
        console.error('Error saving template:', error);
        toast.error(error instanceof Error ? error.message : 'Failed to save template');
      }
    },
    [templates, setTemplates, setTemplateState]
  );

  /**
   * Open save template dialog
   */
  const openSaveDialog = useCallback(() => {
    setTemplateState({ showSaveDialog: true });
  }, [setTemplateState]);

  /**
   * Close save template dialog
   */
  const closeSaveDialog = useCallback(() => {
    setTemplateState({
      showSaveDialog: false,
      newTemplateName: '',
      newTemplateType: '',
    });
  }, [setTemplateState]);

  /**
   * Update dialog form fields
   */
  const updateDialogField = useCallback(
    (field: 'newTemplateName' | 'newTemplateType', value: string) => {
      setTemplateState({ [field]: value });
    },
    [setTemplateState]
  );

  /**
   * Get display text for a template (e.g., "Brand - Product Type")
   * Looks up company name from field options instead of showing ID
   */
  const getTemplateDisplayText = useCallback(
    (templateId: string | null): string => {
      if (!templateId) return '';

      const template = templates.find((t) => t.id.toString() === templateId);
      if (!template) return '';

      // Look up company name from field options
      const companyField = fields.find((f) => f.key === 'company');
      const companyOptions = companyField?.fieldType?.type === 'select'
        ? companyField.fieldType.options
        : [];
      const companyOption = companyOptions?.find(
        (opt) => String(opt.value) === String(template.company)
      );
      const companyName = companyOption?.label || template.company || 'Unknown';

      const productType = template.product_type || 'Unknown';
      return `${companyName} - ${productType}`;
    },
    [templates, fields]
  );

  return {
    // State
    templates,
    templatesLoading,
    templateState,

    // Actions
    loadTemplates,
    applyTemplate,
    applyTemplateToSelected,
    saveTemplate,

    // Helpers
    getTemplateDisplayText,

    // Dialog
    openSaveDialog,
    closeSaveDialog,
    updateDialogField,
  };
};
