import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { bem } from 'utils/bem';
import { Id } from 'backend-api/models';
import { DEFAULT_MIN_SEARCH_LENGTH } from 'common/constants';
import {
  closeAssignCampaignToProjectModal,
  searchProjectsForAssignModal,
  assignCampaignToProject,
  getRecommendedProjectsForAssignModal,
} from 'common/actions';
import {
  isAssignmentModalOpenedSelector,
  isProjectsLoadingForAssignmentSelector,
  searchedProjectsForAssignmentSelector,
  campaignForAssignmentSelector,
  recommendedProjectsForAssignmentSelector,
} from 'common/selectors';
import { ReusableModal } from 'common/components/reusable-modal';
import { ProjectsLoader, ProjectsList, ProjectsEmptyView } from './components';
import { SAssignToProjectModal } from './s-assign-to-project-modal';
import { H4 } from 'common/components/typography';

interface Props {
  onCampaignAssigned?: (projectId: Id) => void;
}

const classes = bem('assign-to-project-modal');

export const AssignToProjectModal = React.memo(({ onCampaignAssigned }: Props) => {
  const dispatch = useDispatch();

  const isOpened = useSelector(isAssignmentModalOpenedSelector);
  const isLoading = useSelector(isProjectsLoadingForAssignmentSelector);
  const campaign = useSelector(campaignForAssignmentSelector);
  const searchedProjects = useSelector(searchedProjectsForAssignmentSelector);
  const recommendedProjects = useSelector(recommendedProjectsForAssignmentSelector);

  const [searchQuery, setSearchQuery] = useState('');

  useEffect(() => {
    if (campaign && isOpened) {
      dispatch(getRecommendedProjectsForAssignModal.request(campaign.uuid));
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [isOpened]);

  useEffect(() => {
    if (searchQuery.length >= DEFAULT_MIN_SEARCH_LENGTH && !!campaign?.uuid) {
      dispatch(searchProjectsForAssignModal.request({ query: searchQuery, campaignUuid: campaign.uuid }));
    }
  }, [dispatch, searchQuery, campaign?.uuid]);

  const onModalClose = useCallback(() => {
    setSearchQuery('');
    dispatch(closeAssignCampaignToProjectModal());
  }, [dispatch]);

  const onSelectProject = useCallback(
    (projectId: Id) => {
      campaign &&
        dispatch(assignCampaignToProject.request({ campaignUuid: campaign.uuid, projectId, onCampaignAssigned }));
      onModalClose();
    },
    [campaign, dispatch, onCampaignAssigned, onModalClose]
  );

  const isSearching = searchQuery.length > 0;
  const hasSearchedProjects = searchedProjects.length > 0;
  const hasRecommendedProjects = recommendedProjects.length > 0;
  const isNoSearchResults = !hasSearchedProjects && isSearching;
  const isNoRecommendedResults = !hasRecommendedProjects && !isSearching;
  const shouldShowEmptyView = isNoSearchResults || isNoRecommendedResults;

  const projects = useMemo(() => (isSearching ? searchedProjects : recommendedProjects), [
    isSearching,
    recommendedProjects,
    searchedProjects,
  ]);

  const sectionTitle = useMemo(() => {
    const title = isSearching ? `Search Results` : 'Recommended Projects';
    return `${title} (${projects.length})`;
  }, [isSearching, projects.length]);

  const body = useMemo(() => {
    if (isLoading) {
      return <ProjectsLoader className={classes('body')} />;
    }

    if (shouldShowEmptyView) {
      return <ProjectsEmptyView isSearching={isSearching} className={classes('body')} />;
    }

    return (
      <>
        {projects.length > 0 && <H4 className={classes('header')}>{sectionTitle}</H4>}
        <div className={classes('body')}>
          <ProjectsList projects={projects} onSelectProject={onSelectProject} />
        </div>
      </>
    );
  }, [isLoading, shouldShowEmptyView, projects, sectionTitle, onSelectProject, isSearching]);

  const title = `Assign ${campaign?.name || 'campaign'} to a Project`;

  return (
    <ReusableModal
      width="880px"
      height="500px"
      isOpen={isOpened}
      title={title}
      searchValue={searchQuery}
      searchPlaceholder="Search by primary artist name, project name, PRS Sub-Project Code, or GRAS number."
      onSearchChange={setSearchQuery}
      onClose={onModalClose}
      dataSelector="assign-campaign-to-project-modal"
      hasSearch
    >
      <SAssignToProjectModal>{body}</SAssignToProjectModal>
    </ReusableModal>
  );
});
