import { useEffect, useMemo, useReducer } from 'react';
import { suggestDeals } from './SearchClient';
import type { SuggestData } from './SearchClient';
import { captureCaught } from '@/lib/observability';

const DEFAULT_DEBOUNCE_MS = 200;
const MIN_QUERY_LENGTH = 2;

export interface UseSearchSuggestReturn {
  suggestions: SuggestData | null;
  loading: boolean;
}

type SuggestState = {
  requestKey: symbol;
  query: string;
  locale: string;
  debounceMs: number;
  suggestions: SuggestData | null;
  loading: boolean;
};

type SuggestAction =
  | {
      type: 'start';
      requestKey: symbol;
      query: string;
      locale: string;
      debounceMs: number;
    }
  | {
      type: 'finish';
      requestKey: symbol;
      query: string;
      locale: string;
      debounceMs: number;
      suggestions: SuggestData | null;
    };

function reduceSuggestState(_state: SuggestState, action: SuggestAction): SuggestState {
  if (action.type === 'start') {
    return { ...action, suggestions: null, loading: true };
  }
  return { ...action, loading: false };
}

export function useSearchSuggest(
  query: string,
  locale: string,
  debounceMs = DEFAULT_DEBOUNCE_MS,
): UseSearchSuggestReturn {
  const [state, dispatch] = useReducer(reduceSuggestState, {
    requestKey: Symbol('initial-search-suggest'),
    query: '',
    locale: '',
    debounceMs: DEFAULT_DEBOUNCE_MS,
    suggestions: null,
    loading: false,
  });
  const trimmed = query.trim();
  const requestKey = useMemo(
    () => Symbol(`search-suggest:${trimmed}:${locale}:${debounceMs}`),
    [trimmed, locale, debounceMs],
  );

  useEffect(() => {
    let active = true;

    if (trimmed.length < MIN_QUERY_LENGTH) {
      return () => {
        active = false;
      };
    }

    const timeoutId = setTimeout(async () => {
      if (!active) return;
      dispatch({
        type: 'start',
        requestKey,
        query: trimmed,
        locale,
        debounceMs,
      });

      try {
        const resp = await suggestDeals({ q: trimmed, locale });
        if (!active) return;
        dispatch({
          type: 'finish',
          requestKey,
          query: trimmed,
          locale,
          debounceMs,
          suggestions: resp.ok && resp.data ? resp.data : null,
        });
      } catch (err) {
        captureCaught(err, {
          scope: 'features.search.useSearchSuggest.suggestDeals',
          severity: 'warning',
        });
        if (!active) return;
        dispatch({
          type: 'finish',
          requestKey,
          query: trimmed,
          locale,
          debounceMs,
          suggestions: null,
        });
      }
    }, debounceMs);
    return () => {
      clearTimeout(timeoutId);
      active = false;
    };
  }, [trimmed, locale, debounceMs, requestKey]);

  const hasValidQuery = trimmed.length >= MIN_QUERY_LENGTH;
  const isCurrentQuery = state.requestKey === requestKey;
  return {
    suggestions: hasValidQuery && isCurrentQuery ? state.suggestions : null,
    loading: hasValidQuery && isCurrentQuery && state.loading,
  };
}
