import { Button, Spinner, Toolbar, Tooltip } from "@fluentui/react-components";
import {
  ArrowResetRegular,
  PauseRegular,
  PlayCircleRegular,
  PlayFilled,
  PowerRegular,
  StopRegular,
} from "@fluentui/react-icons";
import React from "react";
import { GroupApi, TreatmentResult } from "../api/GroupApi";
import { VMGroup } from "../api/ServerApi";
import { VMInfo, VMState } from "../api/VMApi";
import { useAlert } from "../hooks/providers/AlertDialogProvider";
import { useConfirm } from "../hooks/providers/ConfirmDialogProvider";
import { useToast } from "../hooks/providers/ToastProvider";

export function GroupVMAction(p: {
  group: VMGroup;
  state?: VMState;
  vm?: VMInfo;
}): React.ReactElement {
  return (
    <Toolbar>
      <GroupVMButton
        enabled={p.group.can_start}
        icon={<PlayFilled />}
        tooltip="Start"
        group={p.group}
        vm={p.vm}
        allowedStates={["Shutdown", "Shutoff", "Crashed"]}
        currState={p.state}
        needConfirm={false}
        action={GroupApi.StartVM}
      />
      <GroupVMButton
        enabled={p.group.can_suspend}
        icon={<PauseRegular />}
        tooltip="Suspend"
        group={p.group}
        vm={p.vm}
        allowedStates={["Running"]}
        currState={p.state}
        needConfirm={true}
        action={GroupApi.SuspendVM}
      />
      <GroupVMButton
        enabled={p.group.can_resume}
        icon={<PlayCircleRegular />}
        tooltip="Resume"
        group={p.group}
        vm={p.vm}
        allowedStates={["Paused", "PowerManagementSuspended"]}
        currState={p.state}
        needConfirm={false}
        action={GroupApi.ResumeVM}
      />
      <GroupVMButton
        enabled={p.group.can_shutdown}
        icon={<PowerRegular />}
        tooltip="Shutdown"
        group={p.group}
        vm={p.vm}
        allowedStates={["Running"]}
        currState={p.state}
        needConfirm={true}
        action={GroupApi.ShutdownVM}
      />
      <GroupVMButton
        enabled={p.group.can_kill}
        icon={<StopRegular />}
        tooltip="Kill"
        group={p.group}
        vm={p.vm}
        allowedStates={[
          "Running",
          "Paused",
          "PowerManagementSuspended",
          "Blocked",
        ]}
        currState={p.state}
        needConfirm={true}
        action={GroupApi.KillVM}
      />
      <GroupVMButton
        enabled={p.group.can_reset}
        icon={<ArrowResetRegular />}
        tooltip="Reset"
        group={p.group}
        vm={p.vm}
        allowedStates={[
          "Running",
          "Paused",
          "PowerManagementSuspended",
          "Blocked",
        ]}
        currState={p.state}
        needConfirm={true}
        action={GroupApi.ResetVM}
      />
    </Toolbar>
  );
}

function GroupVMButton(p: {
  enabled: boolean;
  icon: React.ReactElement;
  action: (group: VMGroup, vm?: VMInfo) => Promise<TreatmentResult>;
  tooltip: string;
  currState?: VMState;
  allowedStates: VMState[];
  group: VMGroup;
  vm?: VMInfo;
  needConfirm: boolean;
}): React.ReactElement {
  const toast = useToast();
  const confirm = useConfirm();
  const alert = useAlert();

  const [running, setRunning] = React.useState(false);

  const target = p.vm
    ? `the VM ${p.vm.name}`
    : `all the VM of the group ${p.group.id}`;

  const allowed =
    !p.vm || (p.currState && p.allowedStates.includes(p.currState));

  const perform = async () => {
    if (running || !allowed) return;
    try {
      if (
        (!p.vm || p.needConfirm) &&
        !(await confirm(
          `Do you want to perform ${p.tooltip} action on ${target}?`,
          `Confirmation`,
          p.tooltip
        ))
      ) {
        return;
      }

      setRunning(true);

      const result = await p.action(p.group, p.vm);

      toast(
        p.tooltip,
        `${p.tooltip} action on ${target}: ${result.ok} OK / ${result.failed} Failed`,
        "success"
      );
    } catch (e) {
      console.error("Failed to perform group action!", e);

      alert(`Failed to perform ${p.tooltip} action on ${target}: ${e}`);
    } finally {
      setRunning(false);
    }
  };

  if (!p.enabled) return <></>;

  return (
    <Tooltip
      content={`${p.tooltip} ${target}`}
      relationship="description"
      withArrow
    >
      <Button
        icon={running ? <Spinner size="tiny" /> : p.icon}
        onClick={allowed ? perform : undefined}
        disabled={!allowed}
        appearance="subtle"
      />
    </Tooltip>
  );
}
