/**
 * useSearch Hook
 *
 * A composable hook for managing search state with debouncing support.
 * Provides both immediate query (for input display) and debounced query
 * (for API calls).
 *
 * @example
 * ```tsx
 * const search = useSearch({ debounceMs: 300, minLength: 2 });
 *
 * // Use debouncedQuery for API calls
 * const { data } = useQuery(['items', search.debouncedQuery], () =>
 *   fetchItems({ search: search.debouncedQuery })
 * );
 *
 * return (
 *   <div>
 *     <input
 *       type="text"
 *       value={search.query}
 *       onChange={(e) => search.setQuery(e.target.value)}
 *       placeholder="Search..."
 *     />
 *     {search.isPending && <span>Searching...</span>}
 *     <button onClick={search.clear}>Clear</button>
 *   </div>
 * );
 * ```
 *
 * ⚠️ AUTO-GENERATED BY PRISM - DO NOT EDIT
 */

import { useState, useCallback, useEffect, useRef } from 'react';
import type {
  SearchOptions,
  SearchState,
  SearchActions,
  UseSearchResult,
} from '../types';

const DEFAULT_DEBOUNCE_MS = 300;
const DEFAULT_MIN_LENGTH = 0;

/**
 * Hook for managing search state with debouncing.
 *
 * @param options - Search options
 * @returns Search state and actions
 */
export function useSearch(options: SearchOptions = {}): UseSearchResult {
  const {
    initialQuery = '',
    debounceMs = DEFAULT_DEBOUNCE_MS,
    minLength = DEFAULT_MIN_LENGTH,
  } = options;

  const [query, setQueryState] = useState(initialQuery);
  const [debouncedQuery, setDebouncedQuery] = useState(initialQuery);
  const [isPending, setIsPending] = useState(false);

  const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);

  // Update debounced query after delay
  useEffect(() => {
    // Clear any existing timeout
    if (timeoutRef.current) {
      clearTimeout(timeoutRef.current);
    }

    // If query is too short, immediately set debounced to empty
    if (query.length < minLength) {
      setDebouncedQuery('');
      setIsPending(false);
      return;
    }

    // Start pending state
    setIsPending(true);

    // Set new timeout
    timeoutRef.current = setTimeout(() => {
      setDebouncedQuery(query);
      setIsPending(false);
    }, debounceMs);

    // Cleanup on unmount or dependency change
    return () => {
      if (timeoutRef.current) {
        clearTimeout(timeoutRef.current);
      }
    };
  }, [query, debounceMs, minLength]);

  // Computed values
  const isSearching = debouncedQuery.length >= minLength && debouncedQuery.length > 0;

  // Actions
  const setQuery = useCallback((newQuery: string) => {
    setQueryState(newQuery);
  }, []);

  const clear = useCallback(() => {
    setQueryState('');
    setDebouncedQuery('');
    setIsPending(false);
    if (timeoutRef.current) {
      clearTimeout(timeoutRef.current);
      timeoutRef.current = null;
    }
  }, []);

  const reset = useCallback(() => {
    setQueryState(initialQuery);
    setDebouncedQuery(initialQuery);
    setIsPending(false);
    if (timeoutRef.current) {
      clearTimeout(timeoutRef.current);
      timeoutRef.current = null;
    }
  }, [initialQuery]);

  // Build state object
  const state: SearchState = {
    query,
    debouncedQuery,
    isSearching,
    isPending,
  };

  // Build actions object
  const actions: SearchActions = {
    setQuery,
    clear,
    reset,
  };

  return {
    ...state,
    ...actions,
  };
}

export default useSearch;
