/**
 * 일정 검색 관련 커스텀 훅
 * - 검색어 자동완성
 * - 무한 스크롤 검색 결과
 */
import { useState, useEffect, useRef, useMemo, useCallback } from 'react';
import { useInfiniteQuery } from '@tanstack/react-query';
import { useInView } from 'react-intersection-observer';
import useScheduleStore from '@/stores/useScheduleStore';
import * as schedulesApi from '@/api/admin/schedules';

const SEARCH_LIMIT = 20;

export function useScheduleSearch() {
  // Zustand 스토어에서 검색 상태 가져오기
  const {
    searchInput,
    setSearchInput,
    searchTerm,
    setSearchTerm,
    isSearchMode,
    setIsSearchMode,
  } = useScheduleStore();

  // 검색 추천 관련 상태
  const [showSuggestions, setShowSuggestions] = useState(false);
  const [selectedSuggestionIndex, setSelectedSuggestionIndex] = useState(-1);
  const [originalSearchQuery, setOriginalSearchQuery] = useState('');
  const [suggestions, setSuggestions] = useState([]);
  const [isLoadingSuggestions, setIsLoadingSuggestions] = useState(false);

  // Intersection Observer for infinite scroll
  const { ref: loadMoreRef, inView } = useInView({
    threshold: 0,
    rootMargin: '100px',
  });

  // useInfiniteQuery for search
  const {
    data: searchData,
    fetchNextPage,
    hasNextPage,
    isFetchingNextPage,
    isLoading: searchLoading,
  } = useInfiniteQuery({
    queryKey: ['adminScheduleSearch', searchTerm],
    queryFn: async ({ pageParam = 0 }) => {
      return schedulesApi.searchSchedules(searchTerm, { offset: pageParam, limit: SEARCH_LIMIT });
    },
    getNextPageParam: (lastPage) => {
      if (lastPage.hasMore) {
        return lastPage.offset + lastPage.schedules.length;
      }
      return undefined;
    },
    enabled: !!searchTerm && isSearchMode,
  });

  // Flatten search results
  const searchResults = useMemo(() => {
    if (!searchData?.pages) return [];
    return searchData.pages.flatMap((page) => page.schedules);
  }, [searchData]);

  // Auto fetch next page when scrolled to bottom
  const prevInViewRef = useRef(false);
  useEffect(() => {
    if (inView && !prevInViewRef.current && hasNextPage && !isFetchingNextPage && isSearchMode && searchTerm) {
      fetchNextPage();
    }
    prevInViewRef.current = inView;
  }, [inView, hasNextPage, isFetchingNextPage, fetchNextPage, isSearchMode, searchTerm]);

  // 검색어 자동완성 API 호출 (debounce 적용)
  useEffect(() => {
    if (!originalSearchQuery || originalSearchQuery.trim().length === 0) {
      setSuggestions([]);
      return;
    }

    const timeoutId = setTimeout(async () => {
      setIsLoadingSuggestions(true);
      try {
        const response = await fetch(
          `/api/schedules/suggestions?q=${encodeURIComponent(originalSearchQuery)}&limit=10`
        );
        if (response.ok) {
          const data = await response.json();
          setSuggestions(data.suggestions || []);
        }
      } catch (error) {
        console.error('추천 검색어 API 오류:', error);
        setSuggestions([]);
      } finally {
        setIsLoadingSuggestions(false);
      }
    }, 200);

    return () => clearTimeout(timeoutId);
  }, [originalSearchQuery]);

  // 검색 실행
  const handleSearch = useCallback((query) => {
    const trimmedQuery = query?.trim() || '';
    if (trimmedQuery) {
      setSearchTerm(trimmedQuery);
      setIsSearchMode(true);
    }
    setShowSuggestions(false);
    setSelectedSuggestionIndex(-1);
  }, [setSearchTerm, setIsSearchMode]);

  // 검색 모드 종료
  const exitSearchMode = useCallback(() => {
    setIsSearchMode(false);
    setSearchTerm('');
    setSearchInput('');
    setShowSuggestions(false);
    setSuggestions([]);
    setSelectedSuggestionIndex(-1);
    setOriginalSearchQuery('');
  }, [setIsSearchMode, setSearchTerm, setSearchInput]);

  // 검색어 입력 핸들러
  const handleSearchInputChange = useCallback((value) => {
    setSearchInput(value);
    setOriginalSearchQuery(value);
    setSelectedSuggestionIndex(-1);
    if (value.trim()) {
      setShowSuggestions(true);
    } else {
      setShowSuggestions(false);
    }
  }, [setSearchInput]);

  // 추천 검색어 선택
  const handleSuggestionSelect = useCallback((suggestion) => {
    setSearchInput(suggestion);
    handleSearch(suggestion);
  }, [setSearchInput, handleSearch]);

  // 키보드 네비게이션 핸들러
  const handleKeyDown = useCallback((e) => {
    if (!showSuggestions || suggestions.length === 0) {
      if (e.key === 'Enter') {
        handleSearch(searchInput);
      }
      return;
    }

    switch (e.key) {
      case 'ArrowDown':
        e.preventDefault();
        setSelectedSuggestionIndex((prev) => {
          const next = prev < suggestions.length - 1 ? prev + 1 : prev;
          if (next >= 0 && suggestions[next]) {
            setSearchInput(suggestions[next]);
          }
          return next;
        });
        break;
      case 'ArrowUp':
        e.preventDefault();
        setSelectedSuggestionIndex((prev) => {
          const next = prev > 0 ? prev - 1 : -1;
          if (next === -1) {
            setSearchInput(originalSearchQuery);
          } else if (suggestions[next]) {
            setSearchInput(suggestions[next]);
          }
          return next;
        });
        break;
      case 'Enter':
        e.preventDefault();
        if (selectedSuggestionIndex >= 0 && suggestions[selectedSuggestionIndex]) {
          handleSuggestionSelect(suggestions[selectedSuggestionIndex]);
        } else {
          handleSearch(searchInput);
        }
        break;
      case 'Escape':
        setShowSuggestions(false);
        setSelectedSuggestionIndex(-1);
        break;
    }
  }, [showSuggestions, suggestions, selectedSuggestionIndex, searchInput, originalSearchQuery, handleSearch, handleSuggestionSelect, setSearchInput]);

  return {
    // 상태
    searchInput,
    searchTerm,
    isSearchMode,
    setIsSearchMode,
    showSuggestions,
    setShowSuggestions,
    selectedSuggestionIndex,
    suggestions,
    isLoadingSuggestions,
    searchResults,
    searchLoading,
    hasNextPage,
    isFetchingNextPage,

    // 핸들러
    handleSearch,
    exitSearchMode,
    handleSearchInputChange,
    handleSuggestionSelect,
    handleKeyDown,

    // refs
    loadMoreRef,
  };
}

export default useScheduleSearch;
