import React, { useMemo } from "react";
import {
  Menu,
  ButtonIcon,
  CampaignStatuses,
  MenuRow,
  useConfirmationModal,
} from "@komi-app/components";
import "./CampaignMenu.scss";
import { useHistory } from "react-router-dom";
import { campaignService } from "services";
import { useTypedSelector } from "redux/rootReducer";
import { selectUserData } from "redux/User/selector";
import "./CampaignMenu.scss";
import {
  createCampaignEditUrl,
  createCampaignReportUrl,
} from "utils/dca/campaigns";
import notification from "utils/notification";
import { statusesAlwaysApprovedToEdit } from "./Utils";
import { CampaignStatus } from "@komi-app/messaging-sdk";

type CampaignMenuItem = "edit" | "viewReport" | "stop" | "restart" | "delete";

export interface CampaignMenuProps {
  campaignId: string;
  campaignStatus: CampaignStatuses | CampaignStatus;
  campaignName: string;
  omitEditOption?: boolean;
  omitViewReportOption?: boolean;
  refetchTableData?: () => void;
  campaignScheduledTime?: number;
}

const CampaignMenu = ({
  campaignId,
  campaignStatus,
  campaignName,
  omitEditOption = false,
  omitViewReportOption = false,
  refetchTableData = () => {},
  campaignScheduledTime = 0,
}: CampaignMenuProps) => {
  const router = useHistory();
  const confirmationModal = useConfirmationModal();
  const user = useTypedSelector(selectUserData);
  const talentProfileId = String(user?.talentProfile?.id);

  const onStopClick = async () => {
    /**
     * Sendgrid allows us to stop a campaign up to 10 minutes before it is scheduled to be sent.
     * If a campaign is scheduled to be sent in less than 10 minutes, we will show a notification
     * that the campaign can no longer be stopped.
     */

    const sendgridTimeBuffer = 1000 * 60 * 10; // 10 minutes
    //Check if campaign is scheduled to be sent in less than 10 minutes
    if (campaignScheduledTime > Date.now() + sendgridTimeBuffer) {
      // If not, show confirmation modal to delete campaign
      confirmationModal.open({
        className: "campaigns-table-row-menu__modal",
        title: `Are you sure you want to stop the campaign “${campaignName}”?`,
        buttons: [
          {
            label: "No thanks",
            variant: "primary",
            action: "cancel",
          },
          {
            label: "Stop",
            variant: "secondary",
            action: "confirm",
          },
        ],
        onConfirm: async () => {
          try {
            /**
             * Check campaign time again to make sure it hasn't
             * been scheduled to be sent in less than 10 minutes
             */
            if (campaignScheduledTime > Date.now() + sendgridTimeBuffer) {
              await campaignService.stopCampaign(talentProfileId, campaignId);
            } else {
              notification.error({
                message: `${campaignName} is scheduled to be sent in less than 10 minutes and can no longer be stopped`,
              });
            }
          } catch (error) {
            console.error(error);
            notification.error({
              message: `Unable to delete ${campaignName}.`,
            });
          }

          //Refetch table data to show new data
          refetchTableData();
        },
        fullWidthButtons: true,
      });
    } else {
      // If yes, show notification that campaign can no longer be stopped
      notification.error({
        message: `${campaignName} is scheduled to be sent in less than 10 minutes and can no longer be stopped`,
      });
    }
  };

  const onEditClick = () => {
    /**
     * We have a restriction on editing campaigns: only those scheduled
     * for 20 minutes or later in the future can be edited. If a campaign is
     * scheduled to be sent in less than 20 minutes, a notification will appear informing that
     * editing is no longer possible. This limitation exists because we push campaigns to Sendgrid 20
     * minutes before their scheduled sending time.
     */
    const sendgridTimeBuffer = 1000 * 60 * 20; // 20 minutes

    /**
     * Campaigns which have yet not been scheduled are
     * placed in draft. We need to allow editing draft campaign
     */
    if (statusesAlwaysApprovedToEdit.includes(campaignStatus)) {
      return router.push(createCampaignEditUrl(campaignId));
    }

    //Check if campaign is scheduled to be sent 20 minutes or later in the future.
    if (campaignScheduledTime > Date.now() + sendgridTimeBuffer) {
      // If yes, redirect to campaign edit page
      router.push(createCampaignEditUrl(campaignId));
    } else {
      // If yes, show notification that campaign can no longer be stopped
      notification.error({
        message: `${campaignName} is scheduled to be sent in less than 20 minutes and can no longer be updated.`,
      });
    }
  };

  const menuItems = useMemo(() => {
    const item: Record<CampaignMenuItem, MenuRow> = {
      edit: {
        label: "Edit",
        onClick: onEditClick,
      },
      viewReport: {
        label: "View Report",
        onClick: () => router.push(createCampaignReportUrl(campaignId)),
      },
      stop: {
        label: "Stop",
        onClick: onStopClick,
        variant: "warning",
      },
      delete: {
        label: "Delete",
        onClick: () =>
          confirmationModal.open({
            title: `Are you sure you want to delete the campaign “${campaignName}”?`,
            description: `The campaign will be permanently deleted and you won’t be able to recover it or undo this action.`,
            buttons: [
              {
                label: "No thanks",
                variant: "primary",
                action: "cancel",
              },
              {
                label: "Delete",
                variant: "secondary",
                action: "confirm",
              },
            ],
            onConfirm: async () => {
              const isDeleted =
                await campaignService.deleteCampaign(campaignId);

              if (isDeleted) {
                notification.success({
                  message: `Campaign deleted successfully`,
                });
              } else {
                notification.error({
                  message: `Unable to delete campaign.`,
                });
              }

              refetchTableData();
            },
            fullWidthButtons: true,
          }),
        variant: "warning",
      },
      restart: {
        label: "Restart",
        onClick: () =>
          confirmationModal.open({
            title: `Are you sure you want to restart the campaign “${campaignName}”?`,
            buttons: [
              {
                label: "No thanks",
                variant: "primary",
                action: "cancel",
              },
              {
                label: "Restart",
                variant: "secondary",
                action: "confirm",
              },
            ],
            onConfirm: async () => {
              const restartSuccessfull = await campaignService.restartCampaign(
                talentProfileId,
                campaignId,
              );
              if (restartSuccessfull) {
                notification.success({
                  message: `Campaign restarted successfully`,
                });
              } else {
                notification.error({
                  message: `Unable to restart campaign.`,
                });
              }
              //Refetch table data to show new data
              refetchTableData();
            },
            fullWidthButtons: true,
          }),
      },
    };

    let result = {
      [CampaignStatuses.DRAFT]: [item.edit, item.delete],
      [CampaignStatuses.SENDING]: [item.viewReport, item.stop],
      [CampaignStatuses.STOPPED]: [item.edit, item.viewReport, item.restart],
      [CampaignStatuses.COMPLETED]: [item.viewReport],
      [CampaignStatuses.SCHEDULED]: [item.edit, item.stop],
      [CampaignStatuses.CONTINUOUS]: [item.edit, item.viewReport, item.stop],
    }[campaignStatus];

    if (omitEditOption) {
      result = result.filter((x) => x !== item.edit);
    }

    if (omitViewReportOption) {
      result = result.filter((x) => x !== item.viewReport);
    }

    return result;
  }, [
    campaignId,
    campaignStatus,
    campaignName,
    omitEditOption,
    omitViewReportOption,
  ]);

  return (
    <div className="campaigns-table-row-menu">
      <Menu
        child={<ButtonIcon disabled={menuItems?.length === 0} icon="more" />}
        labelTextAlign="left"
        rows={menuItems}
        dataTestId="campaigns-table-menu"
      />
    </div>
  );
};

export default CampaignMenu;
