import React, { useCallback, useEffect, useMemo } from 'react';
import { useSelector } from 'react-redux';
import { debounce } from 'lodash';
import { bem } from 'utils/bem';
import { allProjectsMetaSelector, currentLabelSelector, userProjectsCountSelector } from '../../selectors';
import {
  getAllProjectsTabs,
  getFiltersByStatusWithDefaultOffset,
  getMyProjectDropdownLabelsOptions,
} from '../../transducers';
import { WaveBackground } from 'common/components/wave-background';
import { ResponsiveContainer } from 'common/components/sidebar-form/responsive-container';
import { SAllProjectsSection } from './s-all-projects-section';
import { Tabs } from 'common/components/tabs/tabs';
import { Tab } from 'common/components/tabs/tab';
import { AllProjectsTabHeader } from '../all-projects-tab-header';
import { AllProjects } from '../all-projects';
import { useActiveTab, useProjectsFilters, useTargetValue } from 'projects/hooks';
import { ProjectStatus } from 'backend-api/models';
import {
  COMPLETED_STATUS,
  IN_PROGRESS_STATUS,
  SEARCH_DEBOUNCE_TIME,
  UNASSIGNED_STATUS,
  UPCOMING_STATUS,
} from 'common/constants';
import { OptionalPeriod } from 'common/types';
import { ALL_OPTION_ID } from 'common/components/form/select';
import { AnalyticsEvents, trackEvent } from 'utils/analytic';
import { Select, SelectType } from 'common/components/select';
import { useAppContext } from 'common-v2/hooks';

interface Props {
  gradientEnabled?: boolean;
  className?: string;
}

const classes = bem('all-projects-section');

export const AllProjectsSection = React.memo(
  React.forwardRef<HTMLDivElement, Props>(({ className, gradientEnabled }, ref) => {
    const { labels } = useAppContext();

    const meta = useSelector(allProjectsMetaSelector);
    const userProjectCount = useSelector(userProjectsCountSelector);
    const currentLabel = useSelector(currentLabelSelector);

    const [activeTab, setActiveTab] = useActiveTab();
    const [targetValue, setTargetValue] = useTargetValue();

    const [filters, filtersDispatcher] = useProjectsFilters();

    const labelId = filters.labelId || ALL_OPTION_ID;

    const isUserHasProjects = useMemo(() => !!userProjectCount && userProjectCount > 0, [userProjectCount]);
    const allProjectTabs = useMemo(() => getAllProjectsTabs(labelId, isUserHasProjects, meta), [
      isUserHasProjects,
      labelId,
      meta,
    ]);

    const onPeriodChange = useCallback(
      (period: Array<Date | undefined>) => {
        const [earliestStartDate, latestEndDate] = period;

        const filtersByStatus = getFiltersByStatusWithDefaultOffset(filters.filtersByStatus);

        filtersDispatcher.setFilters({
          earliestStartDate,
          latestEndDate,
          filtersByStatus,
        });
      },
      [filters, filtersDispatcher]
    );

    const debouncedSearch = useMemo(
      () => debounce((value: string) => filtersDispatcher.setSearch(value, true), SEARCH_DEBOUNCE_TIME),
      [filtersDispatcher]
    );

    const onChangeSearchValue = useCallback((value: string) => debouncedSearch(value), [debouncedSearch]);

    const isOptionsEmpty = allProjectTabs.length === 0;

    const period: OptionalPeriod = useMemo(() => [filters.earliestStartDate, filters.latestEndDate], [
      filters.earliestStartDate,
      filters.latestEndDate,
    ]);

    const labelsOptions = useMemo(() => getMyProjectDropdownLabelsOptions(labels, currentLabel), [
      labels,
      currentLabel,
    ]);

    useEffect(() => {
      if (isUserHasProjects && filters.onlyMine !== isUserHasProjects && filters.labelId === undefined) {
        filtersDispatcher.setFilters({ onlyMine: isUserHasProjects });
      }
    }, [isUserHasProjects, filters.onlyMine, filters.labelId, filtersDispatcher]);

    const onSelectLabelId = useCallback(
      labelId => {
        const id = labelId === ALL_OPTION_ID ? undefined : labelId;
        const onlyMine = labelId === ALL_OPTION_ID;
        const filtersByStatus = getFiltersByStatusWithDefaultOffset(filters.filtersByStatus);
        const isUnassignedStatus = filters.status?.id === UNASSIGNED_STATUS.id;

        if (!onlyMine) {
          trackEvent(AnalyticsEvents.ALL_LABEL_PROJECTS_VIEWED);
        }

        filtersDispatcher.setSearch(filters.search);
        filtersDispatcher.setFilters({
          labelId: id,
          filtersByStatus,
          onlyMine,
          status: onlyMine && isUnassignedStatus ? IN_PROGRESS_STATUS : filters.status,
        });
      },
      [filters.filtersByStatus, filters.search, filters.status, filtersDispatcher]
    );

    const getTabTooltipContentByStatus = (status: ProjectStatus) => {
      switch (status.id) {
        case UPCOMING_STATUS.id:
          return (
            <span>
              Projects that have a start date in <br /> the future.
            </span>
          );
        case IN_PROGRESS_STATUS.id:
          return (
            <span>
              Projects that are currently live <br /> according to their start and <br /> end dates.
            </span>
          );
        case COMPLETED_STATUS.id:
          return (
            <span>
              Projects that have an <br /> end date in the past.
            </span>
          );
        case UNASSIGNED_STATUS.id:
          return <span>Projects that don&apos;t have team created.</span>;
        default:
          return undefined;
      }
    };

    const selectClassNames = useMemo(
      () => ({
        singleValue: classes('title'),
      }),
      []
    );

    return (
      <WaveBackground className={className} heightFromChildren={!gradientEnabled}>
        <ResponsiveContainer background={gradientEnabled ? 'transparent' : 'white'}>
          <SAllProjectsSection ref={ref} className={className}>
            {isUserHasProjects ? (
              <Select
                type={SelectType.Simple}
                valueId={labelId}
                valueHandler={onSelectLabelId}
                options={labelsOptions}
                classNames={selectClassNames}
                dataSelector="my-projects-list"
              />
            ) : (
              <span className={classes('title')}>All Projects</span>
            )}
            {!isOptionsEmpty && (
              <Tabs activeTab={activeTab} onChange={setActiveTab} className={classes('tabs')}>
                {allProjectTabs.map(option => {
                  const filtersByStatus = filters.filtersByStatus[option.status.id] || {};

                  const targetOption = option.options.find(option => option.type == targetValue);
                  const targetValueId = targetOption?.id || 0;

                  const searchValue = filters.search;

                  const exportDisabled = targetOption?.count === 0 || option.status.id === 4;

                  const dataSelector = `${option.dataSelector}-projects-tab`;

                  const tooltipContent = getTabTooltipContentByStatus(option.status);

                  return (
                    <Tab
                      key={option.title}
                      title={option.title}
                      badge={option.badge}
                      dataSelector={dataSelector}
                      tooltipContent={tooltipContent}
                      disabled={false}
                    >
                      <AllProjectsTabHeader
                        targetOptions={option.options}
                        targetValue={targetValueId}
                        onChangeTargetValue={setTargetValue}
                        searchValue={searchValue}
                        gradientEnabled={gradientEnabled}
                        onChangeSearchValue={onChangeSearchValue}
                        className={classes('tab-header')}
                        exportDisabled={exportDisabled}
                        onPeriodChange={onPeriodChange}
                        periodValue={period}
                      />
                      <AllProjects
                        targetType={targetValue}
                        filters={filtersByStatus}
                        gradientEnabled={gradientEnabled}
                        className={classes('all-projects')}
                        totalCount={targetOption?.count || 0}
                      />
                    </Tab>
                  );
                })}
              </Tabs>
            )}
          </SAllProjectsSection>
        </ResponsiveContainer>
      </WaveBackground>
    );
  })
);
