import { ref, watch } from 'vue';
import { addressService, TownSuggestion, StreetSuggestion } from '../services/addressService';

/**
 * Debounce utility function
 */
function debounce<T extends (...args: any[]) => void>(fn: T, delay: number): T {
  let timeout: ReturnType<typeof setTimeout>;
  return ((...args: any[]) => {
    clearTimeout(timeout);
    timeout = setTimeout(() => fn(...args), delay);
  }) as T;
}

/**
 * Composable for town autocomplete functionality
 */
export function useTownAutocomplete() {
  const townSuggestions = ref<TownSuggestion[]>([]);
  const isLoadingTowns = ref(false);
  const showTownDropdown = ref(false);
  const highlightedTownIndex = ref(-1);
  const townError = ref('');

  const searchTowns = debounce(async (query: string) => {
    if (!query || query.length < 2) {
      townSuggestions.value = [];
      showTownDropdown.value = false;
      return;
    }

    isLoadingTowns.value = true;
    townError.value = '';

    try {
      const response = await addressService.searchTowns(query);
      if (response.data.ok) {
        townSuggestions.value = response.data.suggestions;
        showTownDropdown.value = townSuggestions.value.length > 0;
        highlightedTownIndex.value = -1;
      }
    } catch (error) {
      console.error('Town search error:', error);
      townError.value = 'Unable to search towns';
      townSuggestions.value = [];
    } finally {
      isLoadingTowns.value = false;
    }
  }, 300);

  const closeTownDropdown = () => {
    // Delay to allow click events to fire
    setTimeout(() => {
      showTownDropdown.value = false;
      highlightedTownIndex.value = -1;
    }, 150);
  };

  const handleTownKeydown = (
    event: KeyboardEvent,
    onSelect: (suggestion: TownSuggestion) => void
  ) => {
    if (!showTownDropdown.value || townSuggestions.value.length === 0) return;

    switch (event.key) {
      case 'ArrowDown':
        event.preventDefault();
        highlightedTownIndex.value = Math.min(
          highlightedTownIndex.value + 1,
          townSuggestions.value.length - 1
        );
        break;
      case 'ArrowUp':
        event.preventDefault();
        highlightedTownIndex.value = Math.max(highlightedTownIndex.value - 1, 0);
        break;
      case 'Enter':
        event.preventDefault();
        if (highlightedTownIndex.value >= 0) {
          onSelect(townSuggestions.value[highlightedTownIndex.value]);
        } else if (townSuggestions.value.length === 1) {
          onSelect(townSuggestions.value[0]);
        }
        break;
      case 'Escape':
        showTownDropdown.value = false;
        highlightedTownIndex.value = -1;
        break;
    }
  };

  return {
    townSuggestions,
    isLoadingTowns,
    showTownDropdown,
    highlightedTownIndex,
    townError,
    searchTowns,
    closeTownDropdown,
    handleTownKeydown,
  };
}

/**
 * Composable for street/address autocomplete functionality
 */
export function useStreetAutocomplete() {
  const streetSuggestions = ref<StreetSuggestion[]>([]);
  const isLoadingStreets = ref(false);
  const showStreetDropdown = ref(false);
  const highlightedStreetIndex = ref(-1);
  const streetError = ref('');

  const searchStreets = debounce(async (town: string, state: string, query: string) => {
    if (!town || !state || !query || query.length < 1) {
      streetSuggestions.value = [];
      showStreetDropdown.value = false;
      return;
    }

    isLoadingStreets.value = true;
    streetError.value = '';

    try {
      const response = await addressService.searchStreets(town, state, query);
      if (response.data.ok) {
        streetSuggestions.value = response.data.suggestions;
        showStreetDropdown.value = streetSuggestions.value.length > 0;
        highlightedStreetIndex.value = -1;
      }
    } catch (error) {
      console.error('Street search error:', error);
      streetError.value = 'Unable to search addresses';
      streetSuggestions.value = [];
    } finally {
      isLoadingStreets.value = false;
    }
  }, 300);

  const closeStreetDropdown = () => {
    setTimeout(() => {
      showStreetDropdown.value = false;
      highlightedStreetIndex.value = -1;
    }, 150);
  };

  const handleStreetKeydown = (
    event: KeyboardEvent,
    onSelect: (suggestion: StreetSuggestion) => void
  ) => {
    if (!showStreetDropdown.value || streetSuggestions.value.length === 0) return;

    switch (event.key) {
      case 'ArrowDown':
        event.preventDefault();
        highlightedStreetIndex.value = Math.min(
          highlightedStreetIndex.value + 1,
          streetSuggestions.value.length - 1
        );
        break;
      case 'ArrowUp':
        event.preventDefault();
        highlightedStreetIndex.value = Math.max(highlightedStreetIndex.value - 1, 0);
        break;
      case 'Enter':
        event.preventDefault();
        if (highlightedStreetIndex.value >= 0) {
          onSelect(streetSuggestions.value[highlightedStreetIndex.value]);
        } else if (streetSuggestions.value.length === 1) {
          onSelect(streetSuggestions.value[0]);
        }
        break;
      case 'Escape':
        showStreetDropdown.value = false;
        highlightedStreetIndex.value = -1;
        break;
    }
  };

  return {
    streetSuggestions,
    isLoadingStreets,
    showStreetDropdown,
    highlightedStreetIndex,
    streetError,
    searchStreets,
    closeStreetDropdown,
    handleStreetKeydown,
  };
}
