import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { RouteComponentProps } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux';
import { useDebounce } from 'react-use';
import { ErrorViewStates } from 'common-v2/components';
import {
  closeManagingCampaigns,
  getProject,
  resetProject,
  resetProjectError,
  resetProjectCampaignsError,
  getDigitalCampaigns,
  manageExternalCampaigns,
  getProjectCampaigns,
} from 'reporting-v2/actions';
import {
  managingCampaignsSelector,
  projectErrorSelector,
  projectSelector,
  projectCampaignsErrorSelector,
  projectCampaignsSelector,
  managingAssignedCampaignsSelector,
} from '../../selectors';
import { ManageCampaignsModal, Reporting } from '../../components';
import { ErrorConfig, GlobalLayout } from 'app/components/global-layout';
import { PermissionErrorModalContainer } from 'modals/permission-error-modal';
import { BEM_CLASS, SReportingContainer } from './s-reporting-container';
import { bem } from 'utils/bem';
import { useHandleGlobalError } from 'common/hooks/use-handle-global-error';
import { CampaignDetails } from 'backend-api/models';
import { SEARCH_DEBOUNCE_TIME } from 'common/constants';
import { getManageCampaignPayload } from './transducers';
import { Loading } from 'common-v2/types';
import { useFormattedDate } from 'common-v2/hooks';
import { getLockedArtist, getProjectName } from 'common-v2/transducers';
import { navigateTo } from 'utils/navigation';
import { paths } from 'app/routing/paths';
import { Head } from 'app/components/head';

const classes = bem(BEM_CLASS);

interface MatchParams {
  id: string;
}

export const ReportingContainer = React.memo(({ match }: RouteComponentProps<MatchParams>) => {
  const dispatch = useDispatch();
  const [search, setSearch] = useState('');

  const project = useSelector(projectSelector);
  const managingCampaigns = useSelector(managingCampaignsSelector);
  const campaignsError = useSelector(projectCampaignsErrorSelector);

  const lockedPrimaryArtist = useMemo(() => {
    if (!project.data) return;
    return getLockedArtist(project.data.targets);
  }, [project.data]);

  const { data: assignedCampaigns } = useSelector(projectCampaignsSelector);
  const { loading: assignedCampaignsLoading } = useSelector(managingAssignedCampaignsSelector);

  const { serverError, globalError } = useHandleGlobalError(projectErrorSelector, resetProjectError);

  const formatDate = useFormattedDate();

  const projectId = parseInt(match.params.id, 10);
  const {
    campaigns: { data: digitalCampaigns, loading: campaignsLoading },
    infiniteLoading,
    total,
  } = managingCampaigns;

  const isReportingLoading = project.loading === Loading.Started;

  useEffect(() => {
    if (!!project.data && !project.data.isClaimed) {
      navigateTo(paths.outdatedNotFound());
    }
  }, [project]);

  const handleSearchChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
    setSearch(event.target.value);
  }, []);

  const clearSearch = useCallback(() => {
    setSearch('');
  }, []);

  const onManagingCampaignsClose = useCallback(() => {
    dispatch(closeManagingCampaigns());
    setSearch('');
  }, [dispatch]);

  useEffect(() => {
    if (assignedCampaignsLoading === Loading.Finished) {
      dispatch(closeManagingCampaigns());
      dispatch(getProjectCampaigns.request(projectId));
    }
  }, [dispatch, assignedCampaignsLoading, projectId]);

  const fetchCampaigns = useCallback(() => {
    dispatch(getDigitalCampaigns.request({ projectId, isInfinite: false }));
  }, [dispatch, projectId]);

  const fetchCampaignsPage = useCallback(() => {
    dispatch(
      getDigitalCampaigns.request({
        projectId,
        offset: digitalCampaigns.length,
        isInfinite: true,
        ...(search ? { freeText: search } : {}),
      })
    );
  }, [dispatch, projectId, digitalCampaigns.length, search]);

  const onApplyCampaigns = useCallback(
    (selectedCampaigns: CampaignDetails[]) => {
      const payload = getManageCampaignPayload(
        projectId,
        assignedCampaigns,
        selectedCampaigns,
        onManagingCampaignsClose
      );

      dispatch(manageExternalCampaigns.request(payload));
    },
    [projectId, assignedCampaigns, onManagingCampaignsClose, dispatch]
  );

  useDebounce(
    () => {
      if (!managingCampaigns.isOpened) return;
      dispatch(getDigitalCampaigns.request({ projectId, isInfinite: false, ...(search ? { freeText: search } : {}) }));
    },
    SEARCH_DEBOUNCE_TIME,
    [dispatch, projectId, search]
  );

  useEffect(() => {
    dispatch(getProject.request(projectId));

    return () => {
      dispatch(resetProject());
      dispatch(resetProjectCampaignsError());
    };
  }, [dispatch, projectId]);

  const refreshAfterErrorHandler = useCallback(() => {
    dispatch(resetProjectError());
    dispatch(getProject.request(projectId));
  }, [dispatch, projectId]);

  const refreshOnCampaignsError = useCallback(() => {
    dispatch(resetProjectCampaignsError());
    dispatch(getProjectCampaigns.request(projectId));
  }, [dispatch, projectId]);

  const errorConfig = useMemo<ErrorConfig>(() => {
    let type = ErrorViewStates.none;

    if (serverError) type = ErrorViewStates.serverError;
    if (globalError) type = ErrorViewStates.globalError;

    return {
      type,
      onRefreshAfterError: refreshAfterErrorHandler,
    };
  }, [refreshAfterErrorHandler, serverError, globalError]);

  useEffect(() => {
    if (!managingCampaigns.isOpened) return;

    if (lockedPrimaryArtist) setSearch(lockedPrimaryArtist.name);

    fetchCampaigns();
  }, [fetchCampaigns, managingCampaigns.isOpened, lockedPrimaryArtist]);

  return (
    <>
      <Head title={getProjectName(project.data)} />
      <SReportingContainer>
        <GlobalLayout className={classes('manhattan-background')} errorConfig={errorConfig}>
          <Reporting
            project={project.data}
            isLoading={isReportingLoading}
            isFailedToLoad={!!campaignsError}
            onRefresh={refreshOnCampaignsError}
          />
        </GlobalLayout>

        <ManageCampaignsModal
          isOpened={managingCampaigns.isOpened}
          processing={assignedCampaignsLoading}
          loading={campaignsLoading}
          infiniteLoading={infiniteLoading}
          campaignsTotalCount={total}
          onClose={onManagingCampaignsClose}
          onApply={onApplyCampaigns}
          campaigns={digitalCampaigns}
          formatDate={formatDate}
          assignedCampaigns={assignedCampaigns}
          refresh={fetchCampaigns}
          onScrollEnd={fetchCampaignsPage}
          searchValue={search}
          onSearchChange={handleSearchChange}
          clearSearch={clearSearch}
        />

        <PermissionErrorModalContainer />
      </SReportingContainer>
    </>
  );
});
