import { type FC, type KeyboardEvent, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useQuery } from 'react-query';

import Box from '@material-hu/mui/Box';

import HuSearch from '@material-hu/components/design-system/Inputs/Search';
import HuPills from '@material-hu/components/design-system/Pills';

import { useDebounce } from 'src/hooks/useDebounce';

import ResultsPanel from './ResultsPanel';
import { searchGlobal } from './services';
import { type PanelMode, type SearchFilter } from './types';
import { useRecentSearches } from './useRecentSearches';

const MAX_WIDTH = 574;

const GlobalSearch: FC = () => {
  const { t } = useTranslation('global_search');
  const inputRef = useRef<HTMLInputElement | null>(null);
  const anchorRef = useRef<HTMLDivElement | null>(null);
  const [value, setValue] = useState('');
  const [isFocused, setIsFocused] = useState(false);
  const [filter, setFilter] = useState<SearchFilter>('all');
  const [isPanelOpen, setIsPanelOpen] = useState(false);

  const { recentSearches, addRecentSearch, clearRecentSearches } =
    useRecentSearches();

  const { debouncedValue, isDebouncing } = useDebounce(value);
  const query = debouncedValue.trim();

  const {
    data: results,
    isFetching,
    isError,
  } = useQuery({
    queryKey: ['global-search', query, filter],
    queryFn: () => searchGlobal(query, filter),
    enabled: isPanelOpen && query.length > 0,
    retry: false,
    staleTime: 60000, // 1 minute
    select: response => response.results,
  });

  const mode: PanelMode = (() => {
    if (!value.trim()) {
      return recentSearches.length > 0 ? 'recent' : 'empty';
    }
    if (isDebouncing || isFetching) return 'loading';
    if (isError) return 'error';
    if (results?.length === 0) return 'no-results';
    return 'results';
  })();

  const closePanel = () => {
    setIsPanelOpen(false);
  };

  const resetSearchState = () => {
    setValue('');
    setFilter('all');
  };

  const handleKeyDown = (
    event: KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>,
  ) => {
    setFilter('all');

    if (event.key === 'Escape') {
      closePanel();
      resetSearchState();
      inputRef.current?.blur();
      return;
    }

    if (event.key === 'Enter' && value.trim().length > 0) {
      handleExploreMore();
    }
  };

  const handleChange = (newValue: string) => {
    if (!isPanelOpen) {
      setIsPanelOpen(true);
    }

    setValue(newValue);
    if (!newValue.trim().length) {
      resetSearchState();
    }
  };

  const handleSelectRecent = (term: string) => {
    setValue(term);
    addRecentSearch(term);
  };

  const handleExploreMore = () => {
    addRecentSearch(value);
    // TODO: navigate to results page
  };

  const handleResultClick = () => {
    addRecentSearch(value);
    closePanel();
  };

  return (
    <Box
      ref={anchorRef}
      sx={{ width: '100%', maxWidth: MAX_WIDTH }}
    >
      <HuSearch
        inputRef={inputRef}
        value={value}
        onChange={handleChange}
        onFocus={() => {
          setIsFocused(true);
          setIsPanelOpen(true);
        }}
        onBlur={() => setIsFocused(false)}
        onKeyDown={handleKeyDown}
        placeholder={t('placeholder')}
        showClear
        endAdornment={
          isFocused && (
            <HuPills
              label="ESC"
              type="neutral"
              size="small"
              hasIcon={false}
            />
          )
        }
        sx={{ width: '100%' }}
      />
      <ResultsPanel
        anchorEl={anchorRef.current}
        open={isPanelOpen}
        onClose={closePanel}
        mode={mode}
        results={results ?? []}
        filter={filter}
        onFilterChange={setFilter}
        onExploreMore={handleExploreMore}
        onResultClick={handleResultClick}
        recentSearches={recentSearches}
        onSelectRecent={handleSelectRecent}
        onClearRecents={clearRecentSearches}
      />
    </Box>
  );
};

export default GlobalSearch;
