import { GlobalSearchModal } from 'app/components/global-search-modal';
import { SearchModal } from 'app/components/search-modal';
import {
  getGlobalSearch,
  getRecentSearch,
  hideGlobalSearch,
  resetGlobalSearch,
  resetRecentSearch,
} from 'common/actions';
import { DEFAULT_MIN_SEARCH_LENGTH, SEARCH_DEBOUNCE_TIME } from 'common/constants';
import { dateFormatSelector, globalSearchSelector } from 'common/selectors';
import { LoadingState } from 'common/types';
import { debounce } from 'lodash';
import React, { useCallback, useEffect, useMemo } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useLocation } from 'react-router-dom';
import { trackEvent, AnalyticsEvents } from 'utils/analytic';
import { bem } from 'utils/bem';
import { BaseState } from 'utils/navigation';
import { RECENT_SEARCH_RESULTS_LIMIT_V2, RECENT_SEARCH_RESULTS_LIMIT, PAGE_LIMIT } from './constants';
import { BEM_CLASS, SGlobalSearchModalContainer } from './s-global-search-modal-container';

interface GlobalSearchModalContainerProps {
  isNewModalActive?: boolean;
}

export const classes = bem(BEM_CLASS);

export const GlobalSearchModalContainer = React.memo(
  ({ isNewModalActive = false }: GlobalSearchModalContainerProps) => {
    const dispatch = useDispatch();
    const location = useLocation<BaseState>();
    const { isActive, query, recent } = useSelector(globalSearchSelector);
    const dateFormat = useSelector(dateFormatSelector);

    const minSearchLength = isNewModalActive ? 1 : DEFAULT_MIN_SEARCH_LENGTH;
    const isRecentViewActive = query.length < minSearchLength;

    const onOverlayClick = useCallback(() => {
      dispatch(hideGlobalSearch());
    }, [dispatch]);

    const debouncedSearch = useMemo(
      () =>
        debounce((value = '') => {
          if (value.length >= minSearchLength) {
            dispatch(getGlobalSearch.request({ query: value, limit: isNewModalActive ? PAGE_LIMIT : undefined }));
          }
        }, SEARCH_DEBOUNCE_TIME),
      [dispatch, isNewModalActive, minSearchLength]
    );

    useEffect(() => {
      if (location.pathname !== location.state?.from) {
        dispatch(hideGlobalSearch());
      }
    }, [location, dispatch]);

    useEffect(() => {
      if (!isActive || !isRecentViewActive) return;
      trackEvent(AnalyticsEvents.RECENT_SEARCHES_OPENED);
    }, [isActive, isRecentViewActive]);

    useEffect(() => {
      if (!isActive) return;

      if (isRecentViewActive && recent.loading === LoadingState.Idle) {
        const limit = isNewModalActive ? RECENT_SEARCH_RESULTS_LIMIT_V2 : RECENT_SEARCH_RESULTS_LIMIT;
        dispatch(getRecentSearch.request({ limit }));
      } else if (!isRecentViewActive) {
        debouncedSearch(query);
      }
    }, [debouncedSearch, dispatch, isActive, isRecentViewActive, query, recent.loading, isNewModalActive]);

    useEffect(() => {
      const overflow = isActive ? 'hidden' : '';
      document.body.style.overflow = overflow;
    }, [isActive]);

    useEffect(() => {
      if (!isRecentViewActive) {
        dispatch(resetGlobalSearch());
      }
    }, [dispatch, isRecentViewActive]);

    useEffect(() => {
      if (!isActive) {
        dispatch(resetGlobalSearch());
        dispatch(resetRecentSearch());
      }
    }, [dispatch, isActive]);

    return (
      <SGlobalSearchModalContainer>
        {isNewModalActive ? (
          <GlobalSearchModal
            className={classes('global-search-modal')}
            dateFormat={dateFormat}
            isRecentViewActive={isRecentViewActive}
            onOverlayClick={onOverlayClick}
          />
        ) : (
          <SearchModal
            className={classes('search-modal')}
            isRecentViewActive={isRecentViewActive}
            onOverlayClick={onOverlayClick}
          />
        )}
      </SGlobalSearchModalContainer>
    );
  }
);
