/* eslint-disable jsx-a11y/heading-has-content -- infer from props */
import { css } from "@emotion/css";
import { useTheme } from "@emotion/react";
import CheckCircleOutlined from "@mui/icons-material/CheckCircleOutlined";
import DoNotDisturbOnOutlined from "@mui/icons-material/DoNotDisturbOnOutlined";
import ErrorOutline from "@mui/icons-material/ErrorOutline";
import Link from "@mui/material/Link";
import {
  cloneElement,
  type ComponentProps,
  type FC,
  forwardRef,
  type HTMLAttributes,
  type ReactElement,
} from "react";
import type { HealthCode, HealthSeverity } from "api/typesGenerated";
import { docs } from "utils/docs";
import { healthyColor } from "./healthyColor";

const CONTENT_PADDING = 36;

export const Header: FC<HTMLAttributes<HTMLDivElement>> = (props) => {
  return (
    <header
      css={{
        display: "flex",
        alignItems: "center",
        justifyContent: "space-between",
        padding: `36px ${CONTENT_PADDING}px`,
      }}
      {...props}
    />
  );
};

export const HeaderTitle: FC<HTMLAttributes<HTMLDivElement>> = (props) => {
  return (
    <h2
      css={{
        margin: 0,
        lineHeight: "1.2",
        fontSize: 20,
        fontWeight: 500,
        display: "flex",
        alignItems: "center",
        gap: 16,
      }}
      {...props}
    />
  );
};

interface HealthIconProps {
  size: number;
  severity: HealthSeverity;
}

export const HealthIcon: FC<HealthIconProps> = ({ size, severity }) => {
  const theme = useTheme();
  const color = healthyColor(theme, severity);
  const Icon = severity === "error" ? ErrorOutline : CheckCircleOutlined;

  return <Icon css={{ width: size, height: size, color }} />;
};

interface HealthyDotProps {
  severity: HealthSeverity;
}

export const HealthyDot: FC<HealthyDotProps> = ({ severity }) => {
  const theme = useTheme();

  return (
    <div
      css={{
        width: 8,
        height: 8,
        borderRadius: 9999,
        backgroundColor: healthyColor(theme, severity),
      }}
    />
  );
};

export const Main: FC<HTMLAttributes<HTMLDivElement>> = (props) => {
  return (
    <main
      css={{
        padding: `0 ${CONTENT_PADDING}px ${CONTENT_PADDING}px`,
        display: "flex",
        flexDirection: "column",
        gap: 36,
      }}
      {...props}
    />
  );
};

export const GridData: FC<HTMLAttributes<HTMLDivElement>> = (props) => {
  return (
    <div
      css={{
        lineHeight: "1.4",
        display: "grid",
        gridTemplateColumns: "auto auto",
        gap: 12,
        columnGap: 48,
        width: "min-content",
        whiteSpace: "nowrap",
      }}
      {...props}
    />
  );
};

export const GridDataLabel: FC<HTMLAttributes<HTMLSpanElement>> = (props) => {
  const theme = useTheme();
  return (
    <span
      css={{
        fontSize: 14,
        fontWeight: 500,
        color: theme.palette.text.secondary,
      }}
      {...props}
    />
  );
};

export const GridDataValue: FC<HTMLAttributes<HTMLSpanElement>> = (props) => {
  const theme = useTheme();
  return (
    <span
      css={{
        fontSize: 14,
        color: theme.palette.text.primary,
      }}
      {...props}
    />
  );
};

export const SectionLabel: FC<HTMLAttributes<HTMLHeadingElement>> = (props) => {
  return (
    <h4
      {...props}
      css={{
        fontSize: 14,
        fontWeight: 500,
        margin: 0,
        lineHeight: "1.2",
        marginBottom: 16,
      }}
    />
  );
};

type PillProps = HTMLAttributes<HTMLDivElement> & {
  icon: ReactElement;
};

export const Pill = forwardRef<HTMLDivElement, PillProps>((props, ref) => {
  const theme = useTheme();
  const { icon, children, ...divProps } = props;

  return (
    <div
      ref={ref}
      css={{
        display: "inline-flex",
        alignItems: "center",
        height: 32,
        borderRadius: 9999,
        border: `1px solid ${theme.palette.divider}`,
        fontSize: 12,
        fontWeight: 500,
        padding: 8,
        gap: 8,
        cursor: "default",
      }}
      {...divProps}
    >
      {cloneElement(icon, { className: css({ width: 14, height: 14 }) })}
      {children}
    </div>
  );
});

type BooleanPillProps = Omit<ComponentProps<typeof Pill>, "icon" | "value"> & {
  value: boolean;
};

export const BooleanPill: FC<BooleanPillProps> = ({
  value,
  children,
  ...divProps
}) => {
  const theme = useTheme();
  const color = value ? theme.palette.success.light : theme.palette.error.light;

  return (
    <Pill
      icon={
        value ? (
          <CheckCircleOutlined css={{ color }} />
        ) : (
          <DoNotDisturbOnOutlined css={{ color }} />
        )
      }
      {...divProps}
    >
      {children}
    </Pill>
  );
};

type LogsProps = { lines: string[] } & HTMLAttributes<HTMLDivElement>;

export const Logs: FC<LogsProps> = ({ lines, ...divProps }) => {
  const theme = useTheme();

  return (
    <div
      css={{
        fontFamily: "monospace",
        fontSize: 13,
        lineHeight: "160%",
        padding: 24,
        backgroundColor: theme.palette.background.paper,
        overflowX: "auto",
        whiteSpace: "pre-wrap",
        wordBreak: "break-all",
      }}
      {...divProps}
    >
      {lines.map((line, index) => (
        <span css={{ display: "block" }} key={index}>
          {line}
        </span>
      ))}
      {lines.length === 0 && (
        <span css={{ color: theme.palette.text.secondary }}>
          No logs available
        </span>
      )}
    </div>
  );
};

interface HealthMessageDocsLinkProps {
  code: HealthCode;
}

export const HealthMessageDocsLink: FC<HealthMessageDocsLinkProps> = ({
  code,
}) => {
  return (
    <Link
      href={docs(`/admin/healthcheck#${code.toLocaleLowerCase()}`)}
      target="_blank"
      rel="noreferrer"
    >
      Docs for {code}
    </Link>
  );
};
