import { useMemo } from "react";
import {
  Menu,
  ButtonIcon,
  MenuRow,
  useConfirmationModal,
} from "@komi-app/components";
import "./CampaignMenu.scss";
import { useHistory } from "react-router-dom";
import { getCampaignSDK } from "services";
import "./CampaignMenu.scss";
import {
  createCampaignEditUrl,
  createCampaignReportUrl,
  createEditSMSCampaignURL,
  createEmailCampaignReportUrl,
} from "utils/dca/campaigns";
import notification from "utils/notification";
import {
  CampaignItem,
  CampaignStatus,
  CampaignType,
  SMS_EDIT_BUFFER_TIME,
} from "@komi-app/messaging-sdk";
import { FLAGS, useFeatureIsOn } from "@komi-app/flags-sdk";
import { useToast } from "@komi-app/creator-ui";

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

export interface CampaignMenuProps {
  campaign: CampaignItem;
  omitEditOption?: boolean;
  omitViewReportOption?: boolean;
  refetchTableData?: () => void;
  assignedNumber: string;
}

const CampaignMenu = ({
  campaign,
  omitEditOption = false,
  omitViewReportOption = false,
  refetchTableData = () => {},
  assignedNumber,
}: CampaignMenuProps) => {
  const router = useHistory();
  const confirmationModal = useConfirmationModal();

  const toast = useToast();

  const isSmartScheduleCampaignEnabled = useFeatureIsOn(
    FLAGS.SMART_SCHEDULE_TALENT,
  );

  const onStopClick = async () => {
    /** A buffer time. If the campaign is set to send within the buffer time,
     *  we do not allow stopping the campaign
     */
    const stopBuffer = 1000 * 60 * 10; // 10 minutes

    //Check if campaign is scheduled to be sent in less than 10 minutes
    if (
      campaign.type === CampaignType.SMART_SCHEDULE_EMAIL ||
      (campaign.scheduledTimestamp &&
        campaign.scheduledTimestamp > Date.now() + stopBuffer)
    ) {
      // 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 “${campaign.name}”?`,
        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 (
              campaign.type === CampaignType.SMART_SCHEDULE_EMAIL ||
              campaign.scheduledTimestamp! > Date.now() + stopBuffer
            ) {
              await getCampaignSDK().updateCampaign({
                id: campaign.id,
                type: CampaignType.SMS,
                status: CampaignStatus.STOPPED,
              });

              toast.createToast({
                text: `You’ve stopped your campaign “${campaign.name}”.`,
                semantic: "success",
                durationMs: 5000,
              });
            } else {
              notification.error({
                message: `${campaign.name} is scheduled to be sent in less than 10 minutes and can no longer be stopped`,
              });
            }
          } catch (error) {
            notification.error({
              message: `We couldn’t stop your campaign. Try again later.`,
            });
          }

          //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: `${campaign.name} is scheduled to be sent in less than 10 minutes and can no longer be stopped`,
      });
    }
  };

  const onEditClick = () => {
    // TODO: ESS_NORMALIZE
    // Temporarily handle smart schedule as follows, until legacy email campaigns
    //   are migrated to the `email_campaign` table
    if (campaign.type === CampaignType.SMART_SCHEDULE_EMAIL) {
      router.push(createCampaignEditUrl(campaign.id, campaign.type));
      return;
    }

    /**
     * If the campaign is scheduled and has less than
     * the buffer time to be sent, do not allow edit.
     */
    if (
      campaign.status === CampaignStatus.SCHEDULED &&
      campaign.scheduledTimestamp! < Date.now() + SMS_EDIT_BUFFER_TIME
    ) {
      notification.error({
        message: `${campaign.name} is scheduled to be sent in less than 10 minutes and can no longer be updated.`,
      });
      return;
    }

    router.push(createEditSMSCampaignURL(campaign.id));
  };

  const onDeleteClick = () => {
    confirmationModal.open({
      title: `Are you sure you want to delete the campaign “${campaign.name}”?`,
      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 () => {
        await getCampaignSDK().hardDeleteOne(
          campaign.id,
          CampaignType.EMAIL.toLowerCase(),
        );

        notification.success({
          message: `Campaign deleted successfully`,
        });

        refetchTableData();
      },
      fullWidthButtons: true,
    });
  };
  const onRestartClick = () => {
    const onConfirmRestart = async () => {
      /**
       * If the campaign is scheduled for more than 10 minutes in the future,
       *    we restart the campaign by scheduling it.
       * If the campaign is under 10 minutes to be sent,
       *    we convert it to Draft so that the user can update its
       *    Schedule time
       */
      if (campaign.scheduledTimestamp! > Date.now() + SMS_EDIT_BUFFER_TIME) {
        const restartSuccessful = await getCampaignSDK().updateCampaign({
          id: campaign.id,
          type: CampaignType.SMS,
          status: CampaignStatus.SCHEDULED,
        });

        if (restartSuccessful) {
          notification.success({
            message: `Campaign restarted successfully`,
          });
        } else {
          notification.error({
            message: `Unable to restart campaign.`,
          });
        }
      } else {
        const restartSuccessful = await getCampaignSDK().updateCampaign({
          id: campaign.id,
          type: CampaignType.SMS,
          status: CampaignStatus.DRAFT,
        });

        if (restartSuccessful) {
          notification.warn({
            message: `The scheduled time for “${campaign.name}” has passed and it’s now in Draft. Schedule it again to send it out.`,
          });
        } else {
          notification.error({
            message: `Unable to restart campaign.`,
          });
        }
      }

      //Refetch table data to show new data
      refetchTableData();
    };

    confirmationModal.open({
      title: `Are you sure you want to restart the campaign “${campaign.name}”?`,
      buttons: [
        {
          label: "No thanks",
          variant: "primary",
          action: "cancel",
        },
        {
          label: "Restart",
          variant: "secondary",
          action: "confirm",
        },
      ],
      onConfirm: onConfirmRestart,
      fullWidthButtons: true,
    });
  };

  //Get menu options list for a stopped campaign
  function stoppedStatusOptions(item: Record<CampaignMenuItem, MenuRow>) {
    const options = [item.edit];

    options.push(item.delete);

    if (assignedNumber !== "") {
      options.push(item.restart);
    }
    return options;
  }

  const menuItems = useMemo(() => {
    const item: Record<CampaignMenuItem, MenuRow> = {
      edit: {
        label: "Edit",
        onClick: onEditClick,
      },
      viewReport: {
        label: "View Report",
        onClick: () => {
          if (campaign.type === CampaignType.SMART_SCHEDULE_EMAIL) {
            router.push(createEmailCampaignReportUrl(campaign.id));
          } else {
            router.push(createCampaignReportUrl(campaign.id));
          }
        },
      },
      stop: {
        label: "Stop",
        onClick: onStopClick,
        variant: "warning",
      },
      delete: {
        label: "Delete",
        onClick: onDeleteClick,
        variant: "warning",
      },
      restart: {
        label: "Restart",
        onClick: onRestartClick,
      },
    };

    const options =
      isSmartScheduleCampaignEnabled &&
      campaign.type === CampaignType.SMART_SCHEDULE_EMAIL
        ? {
            [CampaignStatus.DRAFT]: [item.edit, item.delete],
            [CampaignStatus.SENDING]: [item.viewReport, item.stop],
            [CampaignStatus.STOPPED]: [item.viewReport],
            [CampaignStatus.COMPLETED]: [item.viewReport],
            [CampaignStatus.SCHEDULED]: [item.stop],
            [CampaignStatus.ERRORED]: [],
          }
        : {
            [CampaignStatus.DRAFT]: [item.edit, item.delete],
            [CampaignStatus.SENDING]: [],
            [CampaignStatus.STOPPED]: stoppedStatusOptions(item),
            [CampaignStatus.COMPLETED]: [item.delete],
            [CampaignStatus.SCHEDULED]: [item.edit, item.stop],
            [CampaignStatus.ERRORED]: [],
          };

    let result = options[campaign.status as CampaignStatus];

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

    if (omitViewReportOption) {
      result = result.filter((x) => x !== item.viewReport);
    }
    return result;
  }, [omitEditOption, omitViewReportOption, assignedNumber]);

  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;
