/**
 * ValidationStep Store Selectors
 *
 * Memoized selectors for derived state. Components use these to subscribe
 * only to the state they need, preventing unnecessary re-renders.
 */

import { useMemo } from 'react';
import { useValidationStore } from './validationStore';
import type { RowData, ValidationError } from './types';

// =============================================================================
// Basic State Selectors
// =============================================================================

export const useRows = () => useValidationStore((state) => state.rows);
export const useFields = () => useValidationStore((state) => state.fields);
export const useErrors = () => useValidationStore((state) => state.errors);
export const useFilters = () => useValidationStore((state) => state.filters);
export const useTemplates = () => useValidationStore((state) => state.templates);
export const useTemplatesLoading = () => useValidationStore((state) => state.templatesLoading);
export const useTemplateState = () => useValidationStore((state) => state.templateState);
export const useSelectedRows = () => useValidationStore((state) => state.selectedRows);
export const useInitPhase = () => useValidationStore((state) => state.initPhase);
export const useAiValidation = () => useValidationStore((state) => state.aiValidation);
export const useFieldOptionsLoaded = () => useValidationStore((state) => state.fieldOptionsLoaded);

// =============================================================================
// Cell State Selectors
// =============================================================================

export const useValidatingCells = () => useValidationStore((state) => state.validatingCells);
export const useEditingCells = () => useValidationStore((state) => state.editingCells);

export const useIsCellValidating = (rowIndex: number, field: string) =>
  useValidationStore((state) => state.validatingCells.has(`${rowIndex}-${field}`));

export const useIsCellEditing = (rowIndex: number, field: string) =>
  useValidationStore((state) => state.editingCells.has(`${rowIndex}-${field}`));

// =============================================================================
// UPC Selectors
// =============================================================================

export const useUpcStatus = () => useValidationStore((state) => state.upcStatus);
export const useGeneratedItemNumbers = () => useValidationStore((state) => state.generatedItemNumbers);
export const useInitialUpcValidationDone = () => useValidationStore((state) => state.initialUpcValidationDone);

export const useRowUpcStatus = (rowIndex: number) =>
  useValidationStore((state) => state.upcStatus.get(rowIndex) || 'idle');

export const useRowItemNumber = (rowIndex: number) =>
  useValidationStore((state) => state.generatedItemNumbers.get(rowIndex));

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

export const useProductLinesCache = () => useValidationStore((state) => state.productLinesCache);
export const useSublinesCache = () => useValidationStore((state) => state.sublinesCache);

export const useProductLinesForCompany = (companyId: string) =>
  useValidationStore((state) => state.productLinesCache.get(companyId) || []);

export const useSublinesForLine = (lineId: string) =>
  useValidationStore((state) => state.sublinesCache.get(lineId) || []);

export const useIsLoadingProductLines = (companyId: string) =>
  useValidationStore((state) => state.loadingProductLines.has(companyId));

export const useIsLoadingSublines = (lineId: string) =>
  useValidationStore((state) => state.loadingSublines.has(lineId));

// =============================================================================
// Derived State Selectors (Memoized)
// =============================================================================

/**
 * Get filtered rows based on current filter state
 *
 * PERFORMANCE NOTE: Only subscribes to errors when showErrorsOnly filter is active.
 * This prevents re-renders when errors change but we're not filtering by them.
 */
export const useFilteredRows = () => {
  const rows = useRows();
  const filters = useFilters();
  // Only subscribe to errors when we need to filter by them
  const showErrorsOnly = filters.showErrorsOnly;
  const errors = useValidationStore((state) =>
    showErrorsOnly ? state.errors : null
  );

  return useMemo(() => {
    // No filtering needed if no filters active
    if (!filters.searchText && !showErrorsOnly) {
      return rows;
    }

    // Filter with index tracking to correctly apply errors filter
    const result: RowData[] = [];

    rows.forEach((row, originalIndex) => {
      // Apply search filter
      if (filters.searchText) {
        const searchLower = filters.searchText.toLowerCase();
        const matches = Object.values(row).some((value) =>
          String(value ?? '').toLowerCase().includes(searchLower)
        );
        if (!matches) return;
      }

      // Apply errors-only filter using the ORIGINAL index (not filtered position)
      if (showErrorsOnly && errors) {
        const rowErrors = errors.get(originalIndex);
        if (!rowErrors || Object.keys(rowErrors).length === 0) return;
      }

      result.push(row);
    });

    return result;
  }, [rows, filters, showErrorsOnly, errors]);
};

/**
 * Get filtered row indices (useful for mapping back to original data)
 *
 * PERFORMANCE NOTE: Only subscribes to errors when showErrorsOnly filter is active.
 */
export const useFilteredRowIndices = () => {
  const rows = useRows();
  const filters = useFilters();
  // Only subscribe to errors when we need to filter by them
  const showErrorsOnly = filters.showErrorsOnly;
  const errors = useValidationStore((state) =>
    showErrorsOnly ? state.errors : null
  );

  return useMemo(() => {
    // No filtering needed if no filters active - return all indices
    if (!filters.searchText && !showErrorsOnly) {
      return rows.map((_, index) => index);
    }

    const indices: number[] = [];

    rows.forEach((row, index) => {
      // Apply search filter
      if (filters.searchText) {
        const searchLower = filters.searchText.toLowerCase();
        const matches = Object.values(row).some((value) =>
          String(value ?? '').toLowerCase().includes(searchLower)
        );
        if (!matches) return;
      }

      // Apply errors-only filter
      if (showErrorsOnly && errors) {
        const rowErrors = errors.get(index);
        if (!rowErrors || Object.keys(rowErrors).length === 0) return;
      }

      indices.push(index);
    });

    return indices;
  }, [rows, filters, showErrorsOnly, errors]);
};

/**
 * Get total error count across all rows
 */
export const useTotalErrorCount = () => {
  const errors = useErrors();

  return useMemo(() => {
    let count = 0;
    errors.forEach((rowErrors) => {
      count += Object.keys(rowErrors).length;
    });
    return count;
  }, [errors]);
};

/**
 * Get rows with errors count
 */
export const useRowsWithErrorsCount = () => {
  const errors = useErrors();

  return useMemo(() => {
    let count = 0;
    errors.forEach((rowErrors) => {
      if (Object.keys(rowErrors).length > 0) {
        count++;
      }
    });
    return count;
  }, [errors]);
};

// Stable empty array for cells with no errors
const EMPTY_CELL_ERRORS: ValidationError[] = [];

// Stable empty object for rows with no errors
const EMPTY_ROW_ERRORS: Record<string, ValidationError[]> = {};

/**
 * Get errors for a specific row
 * Uses stable empty object to prevent re-renders
 */
export const useRowErrors = (rowIndex: number) =>
  useValidationStore((state) => state.errors.get(rowIndex) || EMPTY_ROW_ERRORS);

/**
 * Get errors for a specific cell
 * Uses stable empty array to prevent re-renders
 */
export const useCellErrors = (rowIndex: number, field: string): ValidationError[] => {
  return useValidationStore((state) => {
    const rowErrors = state.errors.get(rowIndex);
    if (!rowErrors) return EMPTY_CELL_ERRORS;
    return rowErrors[field] || EMPTY_CELL_ERRORS;
  });
};

/**
 * Check if a row has any errors
 */
export const useRowHasErrors = (rowIndex: number) => {
  const rowErrors = useRowErrors(rowIndex);
  return Object.keys(rowErrors).length > 0;
};

/**
 * Get row data by index
 */
export const useRowData = (rowIndex: number): RowData | undefined =>
  useValidationStore((state) => state.rows[rowIndex]);

/**
 * Get row data by __index (UUID)
 */
export const useRowByIndex = (index: string): RowData | undefined =>
  useValidationStore((state) => state.rows.find((row) => row.__index === index));

/**
 * Check if a row is selected
 */
export const useIsRowSelected = (rowId: string) =>
  useValidationStore((state) => state.selectedRows.has(rowId));

/**
 * Get selected row count
 */
export const useSelectedRowCount = () =>
  useValidationStore((state) => state.selectedRows.size);

/**
 * Get selected row data
 */
export const useSelectedRowData = () => {
  const rows = useRows();
  const selectedRows = useSelectedRows();

  return useMemo(() => {
    return rows.filter((row) => selectedRows.has(row.__index));
  }, [rows, selectedRows]);
};

/**
 * Get selected row indices (numeric)
 */
export const useSelectedRowIndices = () => {
  const rows = useRows();
  const selectedRows = useSelectedRows();

  return useMemo(() => {
    const indices: number[] = [];
    rows.forEach((row, index) => {
      if (selectedRows.has(row.__index)) {
        indices.push(index);
      }
    });
    return indices;
  }, [rows, selectedRows]);
};

/**
 * Check if all rows are selected
 */
export const useAllRowsSelected = () => {
  const rows = useRows();
  const selectedRows = useSelectedRows();

  return useMemo(() => {
    if (rows.length === 0) return false;
    return selectedRows.size === rows.length;
  }, [rows, selectedRows]);
};

/**
 * Check if some (but not all) rows are selected
 */
export const useSomeRowsSelected = () => {
  const rows = useRows();
  const selectedRows = useSelectedRows();

  return useMemo(() => {
    return selectedRows.size > 0 && selectedRows.size < rows.length;
  }, [rows, selectedRows]);
};

// =============================================================================
// Initialization Selectors
// =============================================================================

export const useIsInitializing = () =>
  useValidationStore((state) => state.initPhase !== 'ready' && state.initPhase !== 'idle');

export const useIsReady = () =>
  useValidationStore((state) => state.initPhase === 'ready');

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

export const useIsAiValidating = () =>
  useValidationStore((state) => state.aiValidation.isRunning);

export const useAiValidationProgress = () =>
  useValidationStore((state) => state.aiValidation.progress);

export const useAiValidationResults = () =>
  useValidationStore((state) => state.aiValidation.results);

export const useIsAiChangeReverted = (productIndex: number, fieldKey: string) =>
  useValidationStore((state) =>
    state.aiValidation.revertedChanges.has(`${productIndex}:${fieldKey}`)
  );

/**
 * Get count of AI changes (not reverted)
 */
export const useActiveAiChangesCount = () => {
  const aiValidation = useAiValidation();

  return useMemo(() => {
    if (!aiValidation.results) return 0;
    return aiValidation.results.changes.filter(
      (change) => !aiValidation.revertedChanges.has(`${change.productIndex}:${change.fieldKey}`)
    ).length;
  }, [aiValidation]);
};

// =============================================================================
// Field Selectors
// =============================================================================

/**
 * Get field definition by key
 */
export const useFieldByKey = (key: string) => {
  const fields = useFields();
  return useMemo(() => fields.find((f) => f.key === key), [fields, key]);
};

/**
 * Get field options for a select field
 */
export const useFieldOptions = (fieldKey: string) => {
  const field = useFieldByKey(fieldKey);
  return useMemo(() => {
    if (!field) return [];
    if (field.fieldType.type === 'select' || field.fieldType.type === 'multi-select') {
      return field.fieldType.options || [];
    }
    return [];
  }, [field]);
};

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

/**
 * Get the full copy-down mode state
 */
export const useCopyDownMode = () =>
  useValidationStore((state) => state.copyDownMode);

/**
 * Check if copy-down mode is active (returns boolean for minimal subscription)
 */
export const useIsCopyDownActive = () =>
  useValidationStore((state) => state.copyDownMode.isActive);

/**
 * Check if a specific cell is the copy-down source
 * Returns boolean - minimal subscription, only re-renders when this specific cell's status changes
 */
export const useIsCopyDownSource = (rowIndex: number, fieldKey: string) =>
  useValidationStore((state) =>
    state.copyDownMode.isActive &&
    state.copyDownMode.sourceRowIndex === rowIndex &&
    state.copyDownMode.sourceFieldKey === fieldKey
  );

/**
 * Check if a cell is a valid copy-down target (below source row, same field)
 * Returns boolean - minimal subscription
 */
export const useIsCopyDownTarget = (rowIndex: number, fieldKey: string) =>
  useValidationStore((state) => {
    if (!state.copyDownMode.isActive) return false;
    if (state.copyDownMode.sourceFieldKey !== fieldKey) return false;
    const sourceIndex = state.copyDownMode.sourceRowIndex;
    if (sourceIndex === null) return false;
    return rowIndex > sourceIndex;
  });

/**
 * Check if a cell is within the current copy-down hover range
 * Returns boolean - for highlighting rows that will be affected
 */
export const useIsInCopyDownRange = (rowIndex: number, fieldKey: string) =>
  useValidationStore((state) => {
    if (!state.copyDownMode.isActive) return false;
    if (state.copyDownMode.sourceFieldKey !== fieldKey) return false;
    const sourceIndex = state.copyDownMode.sourceRowIndex;
    const targetIndex = state.copyDownMode.targetRowIndex;
    if (sourceIndex === null || targetIndex === null) return false;
    return rowIndex > sourceIndex && rowIndex <= targetIndex;
  });

// =============================================================================
// Dialog Selectors
// =============================================================================

/**
 * Get full dialog state
 */
export const useDialogs = () =>
  useValidationStore((state) => state.dialogs);

/**
 * Check if template form dialog is open
 */
export const useIsTemplateFormOpen = () =>
  useValidationStore((state) => state.dialogs.templateFormOpen);

/**
 * Get template form initial data
 */
export const useTemplateFormData = () =>
  useValidationStore((state) => state.dialogs.templateFormData);

/**
 * Check if create category dialog is open
 */
export const useIsCreateCategoryOpen = () =>
  useValidationStore((state) => state.dialogs.createCategoryOpen);

// =============================================================================
// Selection Helper Selectors
// =============================================================================

/**
 * Check if there is any selection (returns boolean)
 */
export const useHasSelection = () =>
  useValidationStore((state) => state.selectedRows.size > 0);

/**
 * Check if exactly one row is selected (for "Save as Template")
 */
export const useHasSingleRowSelected = () =>
  useValidationStore((state) => state.selectedRows.size === 1);

/**
 * Get row count (useful for copy-down to check if there are rows below)
 */
export const useRowCount = () =>
  useValidationStore((state) => state.rows.length);
