import React, { useCallback, useMemo } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import {
  approvalRequestsCampaignsSelector,
  approvalRequestsUsersSelector,
  confirmDeleteMediaPlanModalSelector,
  disableRequestApprovalButtonSelector,
  isMediaPlanDropdownVisibleSelector,
  isMediaPlansProcessingSelector,
  mediaPlanModeSelector,
  mediaPlanSelector,
  mediaPlansSelector,
  projectMetricsSelector,
} from 'media-plan/selectors';
import { LoadingState } from 'common/types';
import { Id } from 'backend-api/models';
import {
  changeMediaPlanMode,
  closeDeleteMediaPlanConfirmationModal,
  closeMediaPlansDropdown,
  createMediaPlan,
  deleteMediaPlan,
  editMediaPlan,
  openDeleteMediaPlanConfirmationModal,
  openMediaPlansDropdown,
} from 'media-plan/actions';
import { AnalyticsEvents, trackEvent } from 'utils/analytic';
import { useHeaderPermissions, useShowRequestApprovalButton } from 'media-plan/hooks';
import { includesRole } from 'common/transducers';
import { activeProjectSelector } from 'common/selectors';
import { useProjectCurrencyCode } from 'hooks';
import { BEM_CLASS, SMediaPlanHeaderContainer } from './s-media-plan-header-container';
import { bem } from 'utils/bem';
import { ApprovalControlsLoader, ConfirmationModal, MediaPlansDropdown, SettingsDropdown } from 'media-plan/components';
import { ReleaseInfo } from 'media-plan/components/release-info';
import { SummaryMetrics } from 'common/components/project-header/components/summary-metrics';
import { Tooltip } from 'common-v2/components';
import { Icon } from 'common/components/icon';
import { Button } from 'common/components/button';
import { MediaPlanName } from 'media-plan/components/media-plan-name';
import { TitleLoader } from 'media-plan/components/title-loader';
import { MediaPlanMode } from '../../types';
import { replaceTo } from 'common/utils/navigation';
import { paths } from 'app/routing/paths';
import { MediaPlanModeControls } from '../media-plan-mode-controls';
import { PrimaryLabel } from 'common/components/typography';
import { Team } from 'common/components/team';
import { ROLES } from 'common-v2/constants';

interface Props {
  projectId: Id;
  mediaPlanId?: Id;
  isFullScreen: boolean;
  onFullscreenClick(): void;
  onExportClick(): void;
}

const classes = bem(BEM_CLASS);

export const MediaPlanHeaderContainer = React.memo(
  ({ projectId, mediaPlanId, isFullScreen, onFullscreenClick, onExportClick }: Props) => {
    const dispatch = useDispatch();

    const project = useSelector(activeProjectSelector);
    const mediaPlans = useSelector(mediaPlansSelector);
    const mediaPlan = useSelector(mediaPlanSelector);
    const mediaPlanMode = useSelector(mediaPlanModeSelector);
    const approvalRequestsCampaigns = useSelector(approvalRequestsCampaignsSelector);
    const { loading: projectMetricsLoading, data: projectMetrics } = useSelector(projectMetricsSelector);
    const isMediaPlansProcessing = useSelector(isMediaPlansProcessingSelector);
    const shouldDisableRequestApprovalButton = useSelector(disableRequestApprovalButtonSelector);
    const isMediaPlansDropdownVisible = useSelector(isMediaPlanDropdownVisibleSelector);
    const confirmDeleteMediaPlanModal = useSelector(confirmDeleteMediaPlanModalSelector);
    const approvalRequestsUsers = useSelector(approvalRequestsUsersSelector);

    const shouldShowRequestApprovalButton = useShowRequestApprovalButton(projectId, mediaPlanMode);
    const currencyCode = useProjectCurrencyCode();
    const { canEditMediaPlan, shouldShowMediaPlansDropdown } = useHeaderPermissions(mediaPlans.data, project);

    const isMediaPlanLoading =
      mediaPlan.loading === LoadingState.Started || mediaPlans.loading === LoadingState.Started;
    const isMediaPlanListLoading = mediaPlans.loading === LoadingState.Started;
    const isMetricsLoading =
      projectMetricsLoading === LoadingState.Idle || projectMetricsLoading === LoadingState.Started;

    const activeMediaPlanItem = useMemo(() => {
      if (!mediaPlanId) return;

      return mediaPlans.data.find(mediaPlan => mediaPlan.id === mediaPlanId);
    }, [mediaPlans, mediaPlanId]);

    const onSelectMediaPlan = useCallback(
      (id: Id) => {
        replaceTo(paths.mediaPlan(projectId, id));
      },
      [projectId]
    );

    const onAddNewMediaPlan = useCallback(
      (name: string) => {
        dispatch(createMediaPlan.request({ projectId, payload: { name }, onMediaPlanCreated: onSelectMediaPlan }));
        trackEvent(AnalyticsEvents.MEDIA_PLAN_CREATED, { projectId, projectLabel: project?.label?.name });
      },
      [dispatch, onSelectMediaPlan, project?.label?.name, projectId]
    );

    const onEditMediaPlan = useCallback(
      (id: Id, name: string) => {
        dispatch(editMediaPlan.request({ projectId, mediaPlanId: id, payload: { name } }));
      },
      [dispatch, projectId]
    );

    const onMediaPlanDeleted = useCallback(
      (id: Id) => {
        if (mediaPlanId !== id) {
          return;
        }

        const mediaPlanToShow = mediaPlans.data.filter(mediaPlan => mediaPlan.id !== id)[0];

        if (!mediaPlanToShow) {
          return;
        }

        onSelectMediaPlan(mediaPlanToShow.id);
      },
      [mediaPlanId, mediaPlans.data, onSelectMediaPlan]
    );

    const showConfirmMediaPlanDeletionModal = useCallback(
      (id: Id) => dispatch(openDeleteMediaPlanConfirmationModal(id)),
      [dispatch]
    );

    const handleConfirmMediaPlanDeletionModalResult = useCallback(
      (shouldDeleteMediaPlan: boolean) => {
        if (!shouldDeleteMediaPlan) {
          dispatch(closeDeleteMediaPlanConfirmationModal());
          return;
        }

        if (!confirmDeleteMediaPlanModal.mediaPlanId) return;

        dispatch(
          deleteMediaPlan.request({
            projectId,
            mediaPlanId: confirmDeleteMediaPlanModal.mediaPlanId,
            onMediaPlanDeleted,
          })
        );
        dispatch(closeDeleteMediaPlanConfirmationModal());
        trackEvent(AnalyticsEvents.MEDIA_PLAN_DELETED, { projectId, projectLabel: project?.label?.name });
      },
      [confirmDeleteMediaPlanModal.mediaPlanId, dispatch, onMediaPlanDeleted, project?.label?.name, projectId]
    );

    const onOpenMediaPlansDropdown = useCallback(() => dispatch(openMediaPlansDropdown()), [dispatch]);
    const onCloseMediaPlansDropdown = useCallback(() => dispatch(closeMediaPlansDropdown()), [dispatch]);

    const handleRequestApprovalPress = useCallback(() => {
      trackEvent(AnalyticsEvents.APPROVAL_REQUEST_STARTED, { projectId });
      return dispatch(changeMediaPlanMode(MediaPlanMode.REQUEST_APPROVAL));
    }, [dispatch, projectId]);

    const isUserHasApprovalPermission = useMemo(
      () => !!project?.userRoles && includesRole(project.userRoles, ROLES.APPROVER),
      [project?.userRoles]
    );

    const isApprovalModeAllowed = isUserHasApprovalPermission && approvalRequestsCampaigns.length > 0;

    const mediaPlanModeControl = useMemo(() => {
      if (isMediaPlanLoading && !isApprovalModeAllowed) return <ApprovalControlsLoader />;
      if (mediaPlanMode === MediaPlanMode.REQUEST_APPROVAL || !isApprovalModeAllowed) return null;
      return <MediaPlanModeControls projectId={projectId} mediaPlanId={mediaPlanId} />;
    }, [isMediaPlanLoading, mediaPlanMode, isApprovalModeAllowed, projectId, mediaPlanId]);

    const titleWithLoader = useMemo(
      () =>
        !isMediaPlanListLoading || mediaPlans.data.length !== 0 ? (
          <>
            {shouldShowMediaPlansDropdown ? (
              <MediaPlansDropdown
                mediaPlans={mediaPlans.data}
                mediaPlanId={mediaPlanId}
                onCreateNew={onAddNewMediaPlan}
                onDelete={showConfirmMediaPlanDeletionModal}
                onItemClick={onSelectMediaPlan}
                onEdit={onEditMediaPlan}
                editable={canEditMediaPlan}
                loading={isMediaPlansProcessing}
                onOpen={onOpenMediaPlansDropdown}
                onClose={onCloseMediaPlansDropdown}
                isOpen={isMediaPlansDropdownVisible}
                mediaPlanName={activeMediaPlanItem?.name}
              />
            ) : (
              <MediaPlanName mediaPlanName={activeMediaPlanItem?.name} />
            )}
          </>
        ) : (
          <TitleLoader className={classes('title-loader')} />
        ),
      [
        activeMediaPlanItem?.name,
        canEditMediaPlan,
        isMediaPlanListLoading,
        isMediaPlansDropdownVisible,
        isMediaPlansProcessing,
        mediaPlanId,
        mediaPlans.data,
        onAddNewMediaPlan,
        onCloseMediaPlansDropdown,
        onEditMediaPlan,
        onOpenMediaPlansDropdown,
        onSelectMediaPlan,
        shouldShowMediaPlansDropdown,
        showConfirmMediaPlanDeletionModal,
      ]
    );

    const shouldShowRequesters = approvalRequestsUsers.length > 0 && mediaPlanMode === MediaPlanMode.APPROVAL;
    const shouldShowSettings = mediaPlanMode !== MediaPlanMode.APPROVAL;
    return (
      <SMediaPlanHeaderContainer>
        <div className={classes('title-container')}>
          {titleWithLoader}
          <div className={classes('controls')}>
            {!isMediaPlanLoading && (
              <>
                {shouldShowRequestApprovalButton && (
                  <Button
                    disabled={shouldDisableRequestApprovalButton}
                    variant="transparent"
                    onClick={handleRequestApprovalPress}
                    dataSelector="media-plan-request-approval-button"
                  >
                    Request Approval
                  </Button>
                )}
                {shouldShowRequesters && (
                  <>
                    <PrimaryLabel className={classes('requester-label')}>REQUESTER:</PrimaryLabel>
                    <Team className={classes('requester-team')} users={approvalRequestsUsers} />
                  </>
                )}
                {shouldShowSettings && (
                  <SettingsDropdown className={classes('settings-dropdown')} onExportClick={onExportClick} />
                )}
                <Tooltip content="Full Screen" placement="bottom-end" interactive={false}>
                  <div className={classes('expand')} onClick={onFullscreenClick}>
                    <Icon name={isFullScreen ? 'collapse-bold' : 'expand-bold'} color="black" />
                  </div>
                </Tooltip>
              </>
            )}
          </div>
        </div>
        <div className={classes('mode-container')}>{mediaPlanModeControl}</div>
        <div className={classes('header')}>
          <div className={classes('metrics-container')}>
            <SummaryMetrics projectMetrics={projectMetrics} currencyCode={currencyCode} isLoading={isMetricsLoading} />
          </div>
          <div className={classes('divider')} />
          {mediaPlanId && (
            <ReleaseInfo
              projectId={projectId}
              mediaPlanId={mediaPlanId}
              isInputsDisabled={!canEditMediaPlan}
              className={classes('info')}
            />
          )}
        </div>
        <ConfirmationModal
          text="Deleting media plan cannot be undone"
          action={handleConfirmMediaPlanDeletionModalResult}
          isVisible={confirmDeleteMediaPlanModal.isVisible}
        />
      </SMediaPlanHeaderContainer>
    );
  }
);
