import { type FC, memo, useEffect, useLayoutEffect, useState } from 'react';
import { FormProvider, useForm, useWatch } from 'react-hook-form';

import {
  IconChevronDown,
  IconChevronUp,
  IconSearch,
  IconX,
} from '@material-hu/icons/tabler';
import IconButton from '@material-hu/mui/IconButton';
import Stack from '@material-hu/mui/Stack';
import Typography from '@material-hu/mui/Typography/Typography';

import HuFormInputClassic from '@material-hu/components/design-system/Inputs/Classic/form';

import { useScrollToMessageConversation } from 'src/pages/dashboard/Conversations/contexts/ScrollToMessageConversationContext';
import { useSearchHighlight } from 'src/pages/dashboard/Conversations/contexts/SearchHighlightContext';
import { useLokaliseTranslation } from 'src/utils/i18n';

import { useSearchMessages } from '../../../hooks/useConversationsQueries';

const PREFETCH_THRESHOLD = 10;

type SearchFormValues = { searchMessage: string };

type SearchInputProps = {
  channelId: string;
  isSearchEnabled: boolean;
};

const SearchInput: FC<SearchInputProps> = ({ channelId, isSearchEnabled }) => {
  const { t } = useLokaliseTranslation('forms');
  const { closeSearch, setSearchQuery, setMatchedMessageIds } =
    useSearchHighlight();
  const { scrollToMessage, isScrollingToMessage } =
    useScrollToMessageConversation();
  const [currentMatchIndex, setCurrentMatchIndex] = useState(0);

  const searchForm = useForm<SearchFormValues>({
    defaultValues: { searchMessage: '' },
    mode: 'onChange',
  });

  const queryRaw = useWatch({
    control: searchForm.control,
    name: 'searchMessage',
  });
  const query = queryRaw.trim();

  const { matches, hasNextPage, fetchNextPage, isFetchingNextPage, isSuccess } =
    useSearchMessages({
      channelId,
      query,
      enabled: isSearchEnabled,
    });

  const activeMessageId = matches[currentMatchIndex]?.item?.hu_data?.message_ts;
  const hasMatches = matches.length > 0;
  const noResults = isSuccess && !hasMatches;
  const hasSearchResultsState = hasMatches || noResults;
  const isFirstMatch = currentMatchIndex === 0 || noResults;
  const isLastMatch =
    (currentMatchIndex === matches.length - 1 && !hasNextPage) || noResults;
  const totalMatches = hasNextPage ? '+99' : matches.length;

  // Scroll to active match
  useLayoutEffect(() => {
    if (activeMessageId) scrollToMessage(activeMessageId);
  }, [activeMessageId, scrollToMessage]);

  // Reset index on query change
  useEffect(() => {
    setCurrentMatchIndex(0);
  }, [query]);

  // Update search query in context
  useEffect(() => {
    if (hasMatches) {
      setSearchQuery(query);
    } else {
      setSearchQuery('');
    }
  }, [hasMatches, query, setSearchQuery]);

  // Update searchable message IDs in context to limit highlights
  useEffect(() => {
    if (!hasMatches) {
      setMatchedMessageIds([]);
      return;
    }

    const nextMatchedMessageIds = [
      ...new Set(
        matches
          .map(match => match.item?.hu_data?.message_ts)
          .filter((messageId): messageId is string => !!messageId),
      ),
    ];

    setMatchedMessageIds(nextMatchedMessageIds);
  }, [hasMatches, matches, setMatchedMessageIds]);

  const handleNextMatch = () => {
    if (isScrollingToMessage || !hasSearchResultsState) return;
    if (!isFirstMatch) setCurrentMatchIndex(prev => prev - 1);
  };

  const handlePreviousMatch = () => {
    if (isScrollingToMessage || !hasSearchResultsState) return;
    if (currentMatchIndex < matches.length - 1) {
      setCurrentMatchIndex(prev => prev + 1);
    }
    const remainingItems = matches.length - currentMatchIndex - 1;
    if (
      hasNextPage &&
      remainingItems <= PREFETCH_THRESHOLD &&
      !isFetchingNextPage
    ) {
      fetchNextPage();
    }
  };

  return (
    <Stack
      sx={{
        gap: 2,
        flexDirection: 'row',
        alignItems: 'center',
        justifyContent: 'space-between',
        pb: 1,
        px: 3,
      }}
    >
      <FormProvider {...searchForm}>
        <HuFormInputClassic
          inputProps={{
            maxLength: 500,
            placeholder: '',
            hasCounter: false,
            autoFocus: true,
            sx: {
              '& .MuiInputBase-root': {
                backgroundColor: theme =>
                  theme.palette.new.background.elements.grey,
              },
              '& .MuiInputAdornment-positionEnd svg': {
                width: '16px',
                height: '16px',
              },
              height: '48px',
            },
            startAdornment: <IconSearch />,
          }}
          name="searchMessage"
        />
      </FormProvider>
      <Stack sx={{ gap: 2, flexDirection: 'row', alignItems: 'center' }}>
        {hasMatches && (
          <Typography sx={{ whiteSpace: 'nowrap' }}>
            {t('answers_count', {
              answer: currentMatchIndex + 1,
              total: totalMatches,
            })}
          </Typography>
        )}
        {noResults && <Typography>0</Typography>}
        <IconButton
          onClick={handlePreviousMatch}
          disabled={
            !hasSearchResultsState || isScrollingToMessage || isLastMatch
          }
        >
          <IconChevronUp />
        </IconButton>
        <IconButton
          onClick={handleNextMatch}
          disabled={
            !hasSearchResultsState || isScrollingToMessage || isFirstMatch
          }
        >
          <IconChevronDown />
        </IconButton>
        <IconButton
          variant="secondary"
          onClick={closeSearch}
        >
          <IconX />
        </IconButton>
      </Stack>
    </Stack>
  );
};

export default memo(SearchInput);
