import type { Interpolation, Theme } from "@emotion/react";
import WarningRounded from "@mui/icons-material/WarningRounded";
import Link from "@mui/material/Link";
import Tooltip from "@mui/material/Tooltip";
import type { FC } from "react";
import type { WorkspaceAgent } from "api/typesGenerated";
import { ChooseOne, Cond } from "components/Conditionals/ChooseOne";
import {
  HelpTooltip,
  HelpTooltipContent,
  HelpTooltipText,
  HelpTooltipTitle,
} from "components/HelpTooltip/HelpTooltip";
import { PopoverTrigger } from "components/Popover/Popover";

// If we think in the agent status and lifecycle into a single enum/state I’d
// say we would have: connecting, timeout, disconnected, connected:created,
// connected:starting, connected:start_timeout, connected:start_error,
// connected:ready, connected:shutting_down, connected:shutdown_timeout,
// connected:shutdown_error, connected:off.

const ReadyLifecycle: FC = () => {
  return (
    <div
      role="status"
      data-testid="agent-status-ready"
      aria-label="Ready"
      css={[styles.status, styles.connected]}
    />
  );
};

const StartingLifecycle: FC = () => {
  return (
    <Tooltip title="Starting...">
      <div
        role="status"
        aria-label="Starting..."
        css={[styles.status, styles.connecting]}
      />
    </Tooltip>
  );
};

interface AgentStatusProps {
  agent: WorkspaceAgent;
}

const StartTimeoutLifecycle: FC<AgentStatusProps> = ({ agent }) => {
  return (
    <HelpTooltip>
      <PopoverTrigger role="status" aria-label="Agent timeout">
        <WarningRounded css={styles.timeoutWarning} />
      </PopoverTrigger>

      <HelpTooltipContent>
        <HelpTooltipTitle>Agent is taking too long to start</HelpTooltipTitle>
        <HelpTooltipText>
          We noticed this agent is taking longer than expected to start.{" "}
          <Link
            target="_blank"
            rel="noreferrer"
            href={agent.troubleshooting_url}
          >
            Troubleshoot
          </Link>
          .
        </HelpTooltipText>
      </HelpTooltipContent>
    </HelpTooltip>
  );
};

const StartErrorLifecycle: FC<AgentStatusProps> = ({ agent }) => {
  return (
    <HelpTooltip>
      <PopoverTrigger role="status" aria-label="Start error">
        <WarningRounded css={styles.errorWarning} />
      </PopoverTrigger>
      <HelpTooltipContent>
        <HelpTooltipTitle>Error starting the agent</HelpTooltipTitle>
        <HelpTooltipText>
          Something went wrong during the agent startup.{" "}
          <Link
            target="_blank"
            rel="noreferrer"
            href={agent.troubleshooting_url}
          >
            Troubleshoot
          </Link>
          .
        </HelpTooltipText>
      </HelpTooltipContent>
    </HelpTooltip>
  );
};

const ShuttingDownLifecycle: FC = () => {
  return (
    <Tooltip title="Stopping...">
      <div
        role="status"
        aria-label="Stopping..."
        css={[styles.status, styles.connecting]}
      />
    </Tooltip>
  );
};

const ShutdownTimeoutLifecycle: FC<AgentStatusProps> = ({ agent }) => {
  return (
    <HelpTooltip>
      <PopoverTrigger role="status" aria-label="Stop timeout">
        <WarningRounded css={styles.timeoutWarning} />
      </PopoverTrigger>
      <HelpTooltipContent>
        <HelpTooltipTitle>Agent is taking too long to stop</HelpTooltipTitle>
        <HelpTooltipText>
          We noticed this agent is taking longer than expected to stop.{" "}
          <Link
            target="_blank"
            rel="noreferrer"
            href={agent.troubleshooting_url}
          >
            Troubleshoot
          </Link>
          .
        </HelpTooltipText>
      </HelpTooltipContent>
    </HelpTooltip>
  );
};

const ShutdownErrorLifecycle: FC<AgentStatusProps> = ({ agent }) => {
  return (
    <HelpTooltip>
      <PopoverTrigger role="status" aria-label="Stop error">
        <WarningRounded css={styles.errorWarning} />
      </PopoverTrigger>
      <HelpTooltipContent>
        <HelpTooltipTitle>Error stopping the agent</HelpTooltipTitle>
        <HelpTooltipText>
          Something went wrong while trying to stop the agent.{" "}
          <Link
            target="_blank"
            rel="noreferrer"
            href={agent.troubleshooting_url}
          >
            Troubleshoot
          </Link>
          .
        </HelpTooltipText>
      </HelpTooltipContent>
    </HelpTooltip>
  );
};

const OffLifecycle: FC = () => {
  return (
    <Tooltip title="Stopped">
      <div
        role="status"
        aria-label="Stopped"
        css={[styles.status, styles.disconnected]}
      />
    </Tooltip>
  );
};

const ConnectedStatus: FC<AgentStatusProps> = ({ agent }) => {
  // This is to support legacy agents that do not support
  // reporting the lifecycle_state field.
  if (agent.scripts.length === 0) {
    return <ReadyLifecycle />;
  }
  return (
    <ChooseOne>
      <Cond condition={agent.lifecycle_state === "ready"}>
        <ReadyLifecycle />
      </Cond>
      <Cond condition={agent.lifecycle_state === "start_timeout"}>
        <StartTimeoutLifecycle agent={agent} />
      </Cond>
      <Cond condition={agent.lifecycle_state === "start_error"}>
        <StartErrorLifecycle agent={agent} />
      </Cond>
      <Cond condition={agent.lifecycle_state === "shutting_down"}>
        <ShuttingDownLifecycle />
      </Cond>
      <Cond condition={agent.lifecycle_state === "shutdown_timeout"}>
        <ShutdownTimeoutLifecycle agent={agent} />
      </Cond>
      <Cond condition={agent.lifecycle_state === "shutdown_error"}>
        <ShutdownErrorLifecycle agent={agent} />
      </Cond>
      <Cond condition={agent.lifecycle_state === "off"}>
        <OffLifecycle />
      </Cond>
      <Cond>
        <StartingLifecycle />
      </Cond>
    </ChooseOne>
  );
};

const DisconnectedStatus: FC = () => {
  return (
    <Tooltip title="Disconnected">
      <div
        role="status"
        aria-label="Disconnected"
        css={[styles.status, styles.disconnected]}
      />
    </Tooltip>
  );
};

const ConnectingStatus: FC = () => {
  return (
    <Tooltip title="Connecting...">
      <div
        role="status"
        aria-label="Connecting..."
        css={[styles.status, styles.connecting]}
      />
    </Tooltip>
  );
};

const TimeoutStatus: FC<AgentStatusProps> = ({ agent }) => {
  return (
    <HelpTooltip>
      <PopoverTrigger role="status" aria-label="Timeout">
        <WarningRounded css={styles.timeoutWarning} />
      </PopoverTrigger>
      <HelpTooltipContent>
        <HelpTooltipTitle>Agent is taking too long to connect</HelpTooltipTitle>
        <HelpTooltipText>
          We noticed this agent is taking longer than expected to connect.{" "}
          <Link
            target="_blank"
            rel="noreferrer"
            href={agent.troubleshooting_url}
          >
            Troubleshoot
          </Link>
          .
        </HelpTooltipText>
      </HelpTooltipContent>
    </HelpTooltip>
  );
};

export const AgentStatus: FC<AgentStatusProps> = ({ agent }) => {
  return (
    <ChooseOne>
      <Cond condition={agent.status === "connected"}>
        <ConnectedStatus agent={agent} />
      </Cond>
      <Cond condition={agent.status === "disconnected"}>
        <DisconnectedStatus />
      </Cond>
      <Cond condition={agent.status === "timeout"}>
        <TimeoutStatus agent={agent} />
      </Cond>
      <Cond>
        <ConnectingStatus />
      </Cond>
    </ChooseOne>
  );
};

const styles = {
  status: {
    width: 6,
    height: 6,
    borderRadius: "100%",
    flexShrink: 0,
  },

  connected: (theme) => ({
    backgroundColor: theme.palette.success.light,
    boxShadow: `0 0 12px 0 ${theme.palette.success.light}`,
  }),

  disconnected: (theme) => ({
    backgroundColor: theme.palette.text.secondary,
  }),

  "@keyframes pulse": {
    "0%": {
      opacity: 1,
    },
    "50%": {
      opacity: 0.4,
    },
    "100%": {
      opacity: 1,
    },
  },

  connecting: (theme) => ({
    backgroundColor: theme.palette.info.light,
    animation: "$pulse 1.5s 0.5s ease-in-out forwards infinite",
  }),

  timeoutWarning: (theme) => ({
    color: theme.palette.warning.light,
    width: 14,
    height: 14,
    position: "relative",
  }),

  errorWarning: (theme) => ({
    color: theme.palette.error.main,
    width: 14,
    height: 14,
    position: "relative",
  }),
} satisfies Record<string, Interpolation<Theme>>;
