import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Typography, TYPOGRAPHY_TYPE } from 'gdb-web-shared-components';
import { bem } from 'utils/bem';
import { AnimatePresence } from 'framer-motion';
import errorImageSrc from 'assets/error_failed_to_load.png';
import emptyImageSrc from 'assets/empty_search.png';
import { PAGE_LIMIT } from 'app/containers/global-search-modal-container/constants'; // TODO: Fix after folders structure refactoring
import { globalSearchSelector } from 'common/selectors';
import { LoadingState } from 'common/types';
import { getGlobalSearch, getGlobalSearchPage } from 'common/actions';
import { ErrorView } from 'common-v2/components';
import { DEFAULT_TABS, rootAnimation } from './constants';
import { GlobalSearchResults, Loader } from './components';
import { hasSearchResults } from './transducers';
import { SGlobalSearchModal, BEM_CLASS } from './s-global-search-modal';
import { RecentSearches } from 'app/components/recent-searches';

const classes = bem(BEM_CLASS);

interface GlobalSearchModal {
  className?: string;
  dateFormat: string;
  isRecentViewActive: boolean;
  onOverlayClick(): void;
}

export const GlobalSearchModal = React.memo(
  ({ className, dateFormat, isRecentViewActive, onOverlayClick }: GlobalSearchModal) => {
    const dispatch = useDispatch();

    const [visibleTabs, setVisibleTabs] = useState(DEFAULT_TABS);

    const { top: searchResults, query, isActive } = useSelector(globalSearchSelector);

    const onContentClick = useCallback((e: React.SyntheticEvent) => {
      e.stopPropagation();
    }, []);

    const emptyElement = useMemo(
      () => (
        <div className={classes('empty')}>
          <Typography className={classes('empty-text')} type={TYPOGRAPHY_TYPE.body4}>
            No results found.
            <br />
            Please try another query.
          </Typography>

          <img className={classes('empty-image')} src={emptyImageSrc} alt="Empty results" />
        </div>
      ),
      []
    );

    const errorElement = useCallback(
      (description: React.ReactNode, action: () => void) => (
        <div className={classes('empty')}>
          <ErrorView
            config={{
              bottomImageSrc: errorImageSrc,
              description,
              actionTitle: 'Refresh',
            }}
            action={action}
          />
        </div>
      ),
      []
    );

    const fetchGlobalSearchPage = useCallback(() => {
      if (!searchResults.data) return;

      dispatch(
        getGlobalSearchPage.request({ query, limit: PAGE_LIMIT, offset: searchResults.data.offset + PAGE_LIMIT })
      );
    }, [dispatch, query, searchResults.data]);

    const searchResultsElement = useMemo(() => {
      switch (searchResults.loading) {
        case LoadingState.Idle:
        case LoadingState.Started:
          return (
            <div className={classes('loader')}>
              <Loader />
            </div>
          );
        case LoadingState.Finished:
          return searchResults.data && hasSearchResults(searchResults.data) ? (
            <GlobalSearchResults
              dateFormat={dateFormat}
              data={searchResults.data}
              tabs={visibleTabs}
              updateTabs={setVisibleTabs}
              fetchPage={fetchGlobalSearchPage}
              loading={searchResults.pageLoading}
            />
          ) : (
            emptyElement
          );
        case LoadingState.Failed:
          return errorElement(
            <>
              An error occurred while loading the
              <br />
              Search data, please try again.
            </>,
            () => {
              dispatch(getGlobalSearch.request({ query, limit: PAGE_LIMIT }));
            }
          );
      }
    }, [dateFormat, dispatch, emptyElement, errorElement, fetchGlobalSearchPage, query, searchResults, visibleTabs]);

    useEffect(() => {
      if (isActive) {
        setVisibleTabs(DEFAULT_TABS);
      }
    }, [isActive]);

    return (
      <AnimatePresence exitBeforeEnter>
        {isActive && (
          <SGlobalSearchModal className={className} {...rootAnimation} onClick={onOverlayClick}>
            <div className={classes('content')} onClick={onContentClick}>
              {isRecentViewActive ? <RecentSearches dateFormat={dateFormat} /> : searchResultsElement}
            </div>
          </SGlobalSearchModal>
        )}
      </AnimatePresence>
    );
  }
);
