import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { match, NavLink } from 'react-router-dom';
import { useSelector } from 'react-redux';
import { Location } from 'history';
import { isPlaylists } from 'backend-api/guards';
import { bem } from 'utils/bem';
import { isProjectReportingPath } from 'app/routing/guards';
import { ProjectTab } from 'common-v2/types';
import { dateFormatSelector, projectLoadingSelector, activeProjectSelector } from 'common/selectors';
import { getFlagNameByCountryName, getJoinedNames, includesOnlyApproverRole } from 'common/transducers';
import { capitalize } from 'lodash';
import { Tooltip } from 'common/components/tooltip';
import { TargetsImages } from 'common/components/targets-images';
import { Icon } from 'common/components/icon';
import {
  getCampaignNameConvention,
  getDataSelectorForProjectTab,
  getTerritoryTooltipText,
  getUrlForProjectTab,
} from './transducers';
import { Title } from './components';
import { SProjectHeader } from './s-project-header';
import { PrimaryLabel } from 'common/components/typography';
import { FlagSprite } from 'common/components/flag-sprite';
import { AnalyticsEvents, trackEvent } from 'utils/analytic';
import { showToast, ToastType } from '../toast';
import { ActionBadge } from 'common/components/action-badge';
import { saveToClipboard } from 'utils/copy';
import { Badge, BadgeType } from 'common/components/badge';
import { LoadingState } from 'common/types';
import { TerritoriesLoader } from 'common/components/loaders/territories-loader';
import { convertToDataSelector } from 'common/utils/string';
import { useGetTabs } from './hooks';
import { getProjectName, getProjectSchedule } from 'common-v2/transducers';
import { useAppContext } from 'common-v2/hooks';

interface Props {
  activeTab?: ProjectTab;
  isNoActiveTab?: boolean;
  className?: string;
}

const classes = bem('project-header');

export const ProjectHeader = React.memo(({ activeTab, isNoActiveTab, className }: Props) => {
  const [isInitialLoading, setIsInitialLoading] = useState(true);

  const project = useSelector(activeProjectSelector);
  const projectLoadingState = useSelector(projectLoadingSelector);
  const dateFormat = useSelector(dateFormatSelector);
  const { user: userInfo } = useAppContext();
  const tabs = useGetTabs(project);

  const name = getProjectName(project);
  const projectId = project?.id;
  const prsData = project?.prsData;
  const grasData = project?.grasData;
  const ccpData = project?.ccpData;
  const territories = project?.territories;
  const isClaimed = !!project && project.isClaimed;

  const assignedTargets =
    project &&
    (isPlaylists(project.targets.items)
      ? project.targets.items
      : project.targets.items.filter(item => item.type === 'Primary'));

  const linksList = useMemo(() => {
    const shouldHideLinks = project && includesOnlyApproverRole(project.userRoles);
    return shouldHideLinks ? [] : tabs;
  }, [project, tabs]);

  const schedule = useMemo(() => getProjectSchedule(project, dateFormat, isClaimed), [project, dateFormat, isClaimed]);

  const threeTerritories = useMemo(() => territories?.slice(0, 3) || [], [territories]);
  const otherTerritories = useMemo(() => territories?.slice(3) || [], [territories]);
  const joinedOtherTerritories = useMemo(() => getJoinedNames(otherTerritories), [otherTerritories]);

  const labelName = project?.label?.name;

  const isActiveCallback = useCallback(
    <P, S>(
      _match: match<{ [K in keyof P]?: string | undefined }> | null,
      location: Location<S> | null | undefined,
      path: string
    ) => {
      if (location && isProjectReportingPath(path)) {
        return true;
      }
      return !!_match && _match.url === location?.pathname;
    },
    []
  );

  const campaignNameConvention = useMemo(() => {
    if (!project || !userInfo || !isClaimed) {
      return;
    }

    return getCampaignNameConvention(project.targets.items, getProjectName(project), project.id, userInfo);
  }, [project, userInfo, isClaimed]);

  const onCampaignNameConventionClick = useCallback(() => {
    if (!navigator.clipboard || !project || !campaignNameConvention) return;

    saveToClipboard(campaignNameConvention).then(() => {
      trackEvent(AnalyticsEvents.CAMPAIGN_TEMPLATE_COPIED, { project_id: project.id });
      showToast({
        id: 'campaign-name-convention-copied-toast',
        type: ToastType.Success,
        message: 'Naming convention successfully copied',
        replaceable: true,
      });
    });
  }, [project, campaignNameConvention]);

  const renderBadge = useCallback((title: string, idValue: string | number) => {
    const badgeTitle = `${title} ID: ${idValue}`;

    const onClick = () => {
      saveToClipboard(badgeTitle).then(() => {
        showToast({
          id: `${title}-project-id-copied-toast`,
          type: ToastType.Success,
          message: `${title} ID successfully copied`,
          replaceable: true,
        });
      });
    };

    return (
      <ActionBadge
        iconName="copy"
        title={badgeTitle}
        tooltipText={`Copy ${title} ID.`}
        className={classes('project-id-badge')}
        dataSelector={`project-header-${convertToDataSelector(title)}-id`}
        onClick={onClick}
      />
    );
  }, []);

  const [isProjectIdsExpanded, setIsProjectIdsExpanded] = useState(false);

  const expandProjectIds = useCallback(() => {
    setIsProjectIdsExpanded(!isProjectIdsExpanded);
  }, [isProjectIdsExpanded]);

  const lastBadgeElement = useMemo(
    () =>
      labelName !== undefined ? (
        <Badge
          type={BadgeType.Light}
          className={classes('label-badge')}
          text={labelName}
          dataSelector="label-name-badge"
        />
      ) : null,
    [labelName]
  );

  const isLoading = projectLoadingState === LoadingState.Idle || projectLoadingState === LoadingState.Started;

  useEffect(() => {
    if (isInitialLoading && projectLoadingState === LoadingState.Finished) {
      setIsInitialLoading(false);
    }
  }, [isInitialLoading, projectLoadingState]);

  return (
    <SProjectHeader isNoActiveTab={isNoActiveTab} className={className}>
      <div className={classes('content')}>
        <div className={classes('top-content')}>
          {assignedTargets && assignedTargets.length > 0 && (
            <TargetsImages targets={assignedTargets} className={classes('images')} dataSelector="project-image" gap />
          )}
          <div className={classes('info')}>
            <div className={classes('info-section')}>
              <Title
                text={name}
                project={project}
                dataSelector="project-title"
                className={classes('title')}
                lastBadgeElement={lastBadgeElement}
              />
              {schedule && (
                <>
                  <span data-selector="project-schedule" className={classes('schedule-value')}>
                    {schedule}
                  </span>
                  <Tooltip
                    maxWidth={270}
                    placement="bottom-end"
                    content="Project start date to project end date. Can be edited from the Summary tab."
                  >
                    <div className={classes('schedule-icon')}>
                      <Icon name="time" color="pink" size="general" />
                    </div>
                  </Tooltip>
                </>
              )}
            </div>
            <div className={classes('info-section')}>
              {campaignNameConvention && (
                <ActionBadge
                  iconName="copy"
                  title={campaignNameConvention}
                  tooltipText="Copy campaign naming convention."
                  className={classes('campaign-name-convention')}
                  dataSelector="project-header-campaign-naming-convention"
                  onClick={onCampaignNameConventionClick}
                />
              )}
              <div className={classes('project-ids-container')}>
                {!isProjectIdsExpanded && (
                  <PrimaryLabel className={classes('project-ids-label')}>Show Project IDs</PrimaryLabel>
                )}
                {isProjectIdsExpanded && (
                  <>
                    {projectId && renderBadge('Decibel', projectId)}
                    {prsData && renderBadge('PRS', prsData.id)}
                    {ccpData && renderBadge('CCP', ccpData.id)}
                    {grasData && renderBadge('GRAS', grasData.id)}
                  </>
                )}
                <button
                  className={classes('project-ids-button', { rotated: isProjectIdsExpanded })}
                  onClick={expandProjectIds}
                >
                  <Icon name="expand" color="uncategorizedGray" />
                </button>
              </div>
            </div>
          </div>
        </div>
        <div className={classes('bottom-content')}>
          <div className={classes('routes')}>
            {linksList.map(link => {
              const { label, value, disabled } = link;
              const url = getUrlForProjectTab(value, project);

              const content = (
                <>
                  {label}
                  {activeTab === label && !isNoActiveTab && <div className={classes('line-indicator')} />}
                </>
              );

              const tooltipContent = `Claim this project to use ${capitalize(label)} tab.`;

              const className = classes('menu-item', { disabled: Boolean(disabled) });

              return project && !disabled ? (
                <PrimaryLabel>
                  <NavLink
                    data-selector={getDataSelectorForProjectTab(value)}
                    isActive={(match, location) => isActiveCallback(match, location, url)}
                    key={url}
                    to={url}
                    className={className}
                  >
                    {content}
                  </NavLink>
                </PrimaryLabel>
              ) : project && disabled ? (
                <Tooltip key={url} content={tooltipContent} maxWidth={180}>
                  <div>
                    <PrimaryLabel className={className}>{content}</PrimaryLabel>
                  </div>
                </Tooltip>
              ) : (
                <PrimaryLabel key={url} className={className}>
                  {content}
                </PrimaryLabel>
              );
            })}
          </div>
          <div className={classes('territories-container')}>
            {isLoading && isInitialLoading ? (
              <TerritoriesLoader />
            ) : (
              threeTerritories.length > 0 && (
                <>
                  <div className={classes('territories-container')}>
                    {threeTerritories.map(territory => {
                      const flag = getFlagNameByCountryName(territory.name);
                      const tooltipContent = getTerritoryTooltipText(threeTerritories, territory);
                      return (
                        <Tooltip key={territory.id} content={tooltipContent}>
                          <div>
                            <FlagSprite className={classes('country-icon')} icon={flag} size={22} />
                          </div>
                        </Tooltip>
                      );
                    })}
                  </div>
                  {otherTerritories.length > 0 && (
                    <Tooltip placement="bottom-end" content={joinedOtherTerritories}>
                      <div className={classes('more-territories-container')}>
                        <span
                          data-selector="project-header-more-countries"
                          className={classes('more-territories-text')}
                        >
                          +{otherTerritories.length}
                        </span>
                      </div>
                    </Tooltip>
                  )}
                </>
              )
            )}
          </div>
        </div>
      </div>
    </SProjectHeader>
  );
});
