import { useState, useEffect, useMemo, useCallback } from 'react';
import { supabase } from '@/integrations/supabase/client';
import { Park, Ride, Company } from '@/types/database';
import { logger } from '@/lib/logger';
import * as storage from '@/lib/localStorage';
import { toast } from 'sonner';
import { getErrorMessage } from '@/lib/errorHandler';

export interface SearchResult {
  id: string;
  type: 'park' | 'ride' | 'company';
  title: string;
  subtitle: string;
  image?: string;
  rating?: number;
  slug?: string;
  data: Park | Ride | Company;
}

interface UseSearchOptions {
  types?: ('park' | 'ride' | 'company')[];
  limit?: number;
  minQuery?: number;
  debounceMs?: number;
}

// Hoist default values to prevent recreating on every render
const DEFAULT_TYPES: ('park' | 'ride' | 'company')[] = ['park', 'ride', 'company'];
const DEFAULT_LIMIT = 10;
const DEFAULT_MIN_QUERY = 2;
const DEFAULT_DEBOUNCE_MS = 300;

export function useSearch(options: UseSearchOptions = {}) {
  // All hooks declarations in stable order
  const [query, setQuery] = useState('');
  const [results, setResults] = useState<SearchResult[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [recentSearches, setRecentSearches] = useState<string[]>([]);
  const [debouncedQuery, setDebouncedQuery] = useState('');

  // Use useMemo to stabilize options, but use safe defaults to prevent undefined errors during HMR
  const stableOptions = useMemo(() => {
    const safeOptions = options || {};
    return {
      types: safeOptions.types || DEFAULT_TYPES,
      limit: safeOptions.limit ?? DEFAULT_LIMIT,
      minQuery: safeOptions.minQuery ?? DEFAULT_MIN_QUERY,
      debounceMs: safeOptions.debounceMs ?? DEFAULT_DEBOUNCE_MS,
    };
  }, [options]);

  const { types, limit, minQuery, debounceMs } = stableOptions;

  useEffect(() => {
    const timer = setTimeout(() => {
      setDebouncedQuery(query);
    }, debounceMs);

    return () => clearTimeout(timer);
  }, [query, debounceMs]);

  // Load recent searches from localStorage
  useEffect(() => {
    const searches = storage.getJSON<string[]>('thrillwiki_recent_searches', []);
    if (Array.isArray(searches)) {
      setRecentSearches(searches);
    }
  }, []);

  // Search function
  const search = useCallback(async (searchQuery: string) => {
    if (searchQuery.length < minQuery) {
      setResults([]);
      setError(null);
      return;
    }

    setLoading(true);
    setError(null);
    try {
      const searchResults: SearchResult[] = [];

      // Search parks
      if (types.includes('park')) {
        const { data: parks } = await supabase
          .from('parks')
          .select(`
            *,
            location:locations(*),
            operator:companies!parks_operator_id_fkey(*)
          `)
          .or(`name.ilike.%${searchQuery}%,description.ilike.%${searchQuery}%`)
          .limit(Math.ceil(limit / types.length));

        parks?.forEach((park) => {
          searchResults.push({
            id: park.id,
            type: 'park',
            title: park.name,
            subtitle: [park.location?.city, park.location?.state_province, park.location?.country].filter(Boolean).join(', '),
            image: park.banner_image_url || park.card_image_url || undefined,
            rating: park.average_rating ?? undefined,
            slug: park.slug,
            data: park
          });
        });
      }

      // Search rides
      if (types.includes('ride')) {
        const { data: rides } = await supabase
          .from('rides')
          .select(`
            *,
            park:parks!inner(name, slug),
            manufacturer:companies!rides_manufacturer_id_fkey(*)
          `)
          .or(`name.ilike.%${searchQuery}%,description.ilike.%${searchQuery}%`)
          .limit(Math.ceil(limit / types.length));

        rides?.forEach((ride) => {
          searchResults.push({
            id: ride.id,
            type: 'ride',
            title: ride.name,
            subtitle: `at ${ride.park?.name || 'Unknown Park'}`,
            image: ride.image_url || undefined,
            rating: ride.average_rating ?? undefined,
            slug: ride.slug,
            data: ride
          });
        });
      }

      // Search companies
      if (types.includes('company')) {
        const { data: companies } = await supabase
          .from('companies')
          .select('id, name, slug, description, company_type, logo_url, average_rating, review_count')
          .or(`name.ilike.%${searchQuery}%,description.ilike.%${searchQuery}%`)
          .limit(Math.ceil(limit / types.length));

        companies?.forEach((company) => {
          searchResults.push({
            id: company.id,
            type: 'company',
            title: company.name,
            subtitle: company.company_type?.replace('_', ' ').replace(/\b\w/g, l => l.toUpperCase()) || 'Company',
            image: company.logo_url || undefined,
            slug: company.slug,
            data: company
          });
        });
      }

      // Sort by relevance (exact matches first, then partial matches)
      searchResults.sort((a, b) => {
        const aExact = a.title.toLowerCase().startsWith(searchQuery.toLowerCase());
        const bExact = b.title.toLowerCase().startsWith(searchQuery.toLowerCase());
        
        if (aExact && !bExact) return -1;
        if (!aExact && bExact) return 1;
        
        return a.title.localeCompare(b.title);
      });

      setResults(searchResults.slice(0, limit));
    } catch (error: unknown) {
      const errorMsg = getErrorMessage(error);
      logger.error('Search failed', { 
        query: searchQuery, 
        types, 
        error: errorMsg 
      });
      
      toast.error('Search failed', {
        description: 'Unable to search. Please try again.',
      });
      
      setError('Failed to search. Please try again.');
      setResults([]);
    } finally {
      setLoading(false);
    }
  }, [types, limit, minQuery]);

  // Effect for debounced search
  useEffect(() => {
    if (debouncedQuery) {
      search(debouncedQuery);
    } else {
      setResults([]);
    }
  }, [debouncedQuery, search]);

  // Save search to recent searches
  const saveSearch = (searchQuery: string) => {
    if (!searchQuery.trim()) return;
    
    const updated = [searchQuery, ...recentSearches.filter(s => s !== searchQuery)].slice(0, 5);
    setRecentSearches(updated);
    storage.setJSON('thrillwiki_recent_searches', updated);
  };

  // Clear recent searches
  const clearRecentSearches = () => {
    setRecentSearches([]);
    storage.removeItem('thrillwiki_recent_searches');
  };

  // Get suggestions (recent searches when no query)
  const suggestions = useMemo(() => {
    if (query.length > 0) return [];
    return recentSearches.map(search => ({
      id: search,
      type: 'suggestion' as const,
      title: search,
      subtitle: 'Recent search',
      data: null
    }));
  }, [query, recentSearches]);

  return {
    query,
    setQuery,
    results,
    suggestions,
    loading,
    error,
    recentSearches,
    saveSearch,
    clearRecentSearches,
    search
  };
}