/**
 * Address Autocomplete Hook
 *
 * Provides address search and geocoding functionality with debouncing
 */

import { useState, useCallback, useEffect, useRef } from 'react';
import { geocodingApi, AddressResult } from '@/services/api/geocodingApi';

interface UseAddressAutocompleteOptions {
  countryCode?: string;
  limit?: number;
  debounceMs?: number;
  minQueryLength?: number;
}

interface UseAddressAutocompleteReturn {
  query: string;
  setQuery: (query: string) => void;
  results: AddressResult[];
  isLoading: boolean;
  error: string | null;
  selectedAddress: AddressResult | null;
  selectAddress: (address: AddressResult) => void;
  clearSelection: () => void;
  clearResults: () => void;
}

export function useAddressAutocomplete(
  options: UseAddressAutocompleteOptions = {}
): UseAddressAutocompleteReturn {
  const {
    countryCode = 'es',
    limit = 10,
    debounceMs = 500,
    minQueryLength = 3
  } = options;

  const [query, setQuery] = useState('');
  const [results, setResults] = useState<AddressResult[]>([]);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [selectedAddress, setSelectedAddress] = useState<AddressResult | null>(null);

  const debounceTimerRef = useRef<NodeJS.Timeout | null>(null);
  const abortControllerRef = useRef<AbortController | null>(null);

  const searchAddresses = useCallback(
    async (searchQuery: string) => {
      // Clear previous results if query is too short
      if (searchQuery.trim().length < minQueryLength) {
        setResults([]);
        setError(null);
        return;
      }

      // Cancel previous request if still pending
      if (abortControllerRef.current) {
        abortControllerRef.current.abort();
      }

      abortControllerRef.current = new AbortController();

      setIsLoading(true);
      setError(null);

      try {
        const searchResults = await geocodingApi.searchAddresses(
          searchQuery,
          countryCode,
          limit
        );

        setResults(searchResults);
        setError(null);
      } catch (err: any) {
        // Ignore abort errors
        if (err.name === 'AbortError' || err.name === 'CanceledError') {
          return;
        }

        console.error('Address search error:', err);
        setError(err.message || 'Failed to search addresses');
        setResults([]);
      } finally {
        setIsLoading(false);
      }
    },
    [countryCode, limit, minQueryLength]
  );

  // Debounced search effect
  useEffect(() => {
    // Clear previous timer
    if (debounceTimerRef.current) {
      clearTimeout(debounceTimerRef.current);
    }

    // Don't search if query is empty or selected address matches query
    if (!query || (selectedAddress && selectedAddress.display_name === query)) {
      setResults([]);
      return;
    }

    // Set new timer
    debounceTimerRef.current = setTimeout(() => {
      searchAddresses(query);
    }, debounceMs);

    // Cleanup
    return () => {
      if (debounceTimerRef.current) {
        clearTimeout(debounceTimerRef.current);
      }
    };
  }, [query, debounceMs, searchAddresses, selectedAddress]);

  const selectAddress = useCallback((address: AddressResult) => {
    setSelectedAddress(address);
    setQuery(address.display_name);
    setResults([]);
    setError(null);
  }, []);

  const clearSelection = useCallback(() => {
    setSelectedAddress(null);
    setQuery('');
    setResults([]);
    setError(null);
  }, []);

  const clearResults = useCallback(() => {
    setResults([]);
    setError(null);
  }, []);

  return {
    query,
    setQuery,
    results,
    isLoading,
    error,
    selectedAddress,
    selectAddress,
    clearSelection,
    clearResults
  };
}
