/**
 * useSearchIndex Hook
 * Manages the searchable field registry and filters settings based on query.
 *
 * Supports two modes:
 * 1. Schema-based: Auto-populates from settingsSchema.ts (recommended)
 * 2. Manual registration: Fields register themselves via SearchableField component
 *
 * The schema-based approach ensures search stays in sync with available settings,
 * similar to iOS Settings search. Fields with requiresToggle will redirect to
 * their parent toggle when the associated setting is disabled.
 */
import { useState, useCallback, useMemo, useEffect } from "react";
import type { SearchableFieldData } from "../components/SearchResultsView";
import { schemaToSearchableFields } from "../settingsSchema";
import type { RequiresToggle } from "../settingsSchema";
import { calculateSearchRelevance } from "../searchUtils";

/** Extended field data that includes keywords and requiresToggle for search */
export interface SearchableFieldDataWithKeywords extends SearchableFieldData {
  keywords?: string[];
  requiresToggle?: RequiresToggle;
}

export interface UseSearchIndexOptions {
  /** Enable schema-based auto-population (default: true) */
  useSchema?: boolean;
}

export interface UseSearchIndexReturn {
  /** Current searchable fields registry */
  fields: SearchableFieldDataWithKeywords[];
  /** Register a new searchable field (for manual mode) */
  registerField: (field: SearchableFieldDataWithKeywords) => void;
  /** Unregister a field by ID */
  unregisterField: (id: string) => void;
  /** Clear all registered fields */
  clearFields: () => void;
  /** Filter fields by query, sorted by relevance */
  search: (query: string) => SearchableFieldDataWithKeywords[];
}

/**
 * Hook to manage searchable field registry and perform searches.
 * All fields are indexed for search discovery. Fields with requiresToggle
 * will be handled by the search result handler to redirect to parent toggles.
 *
 * @example
 * // Schema-based (recommended)
 * const { search } = useSearchIndex({ useSchema: true });
 *
 * // Manual registration (legacy)
 * const { registerField, unregisterField, search } = useSearchIndex({ useSchema: false });
 */
export function useSearchIndex(
  options: UseSearchIndexOptions = {},
): UseSearchIndexReturn {
  const { useSchema = true } = options;
  const [fieldsMap, setFieldsMap] = useState<
    Map<string, SearchableFieldDataWithKeywords>
  >(new Map());

  // Initialize from schema on mount.
  useEffect(() => {
    if (!useSchema) return;

    const schemaFields = schemaToSearchableFields();
    const newMap = new Map<string, SearchableFieldDataWithKeywords>();

    for (const field of schemaFields) {
      newMap.set(field.id, field);
    }

    setFieldsMap(newMap);
  }, [useSchema]);

  const registerField = useCallback(
    (field: SearchableFieldDataWithKeywords) => {
      setFieldsMap((prev) => {
        const next = new Map(prev);
        next.set(field.id, field);
        return next;
      });
    },
    [],
  );

  const unregisterField = useCallback((id: string) => {
    setFieldsMap((prev) => {
      const next = new Map(prev);
      next.delete(id);
      return next;
    });
  }, []);

  const clearFields = useCallback(() => {
    setFieldsMap(new Map());
  }, []);

  const fields = useMemo(() => Array.from(fieldsMap.values()), [fieldsMap]);

  const search = useCallback(
    (query: string): SearchableFieldDataWithKeywords[] => {
      if (!query.trim()) return [];

      // Score all fields and filter to those with positive scores
      const scoredFields = fields
        .map((field) => ({
          field,
          score: calculateSearchRelevance(query, field),
        }))
        .filter(({ score }) => score > 0);

      // Sort by score descending (most relevant first)
      scoredFields.sort((a, b) => b.score - a.score);

      return scoredFields.map(({ field }) => field);
    },
    [fields],
  );

  return {
    fields,
    registerField,
    unregisterField,
    clearFields,
    search,
  };
}
