"use client";

import Box from "@mui/material/Box";
import { alpha, useTheme } from "@mui/material/styles";

import {
  Cell,
  Pie,
  PieChart,
  ResponsiveContainer,
} from "recharts";

import { usePlenaryChartReady } from "./use-plenary-chart-ready";

type PlenaryDonutChartData = {
  label: string;
  value: number;
  color: string;
  labelText?: string;
};

type PlenaryDonutChartProps = {
  centerLabel: string;
  centerValue: string;
  data: PlenaryDonutChartData[];
  height?: number;
  centerFill?: string;
};

type DonutLabelProps = {
  index?: number;
  cx?: number;
  cy?: number;
  midAngle?: number;
  innerRadius?: number;
  outerRadius?: number;
};

export function PlenaryDonutChart({
  centerLabel,
  centerValue,
  data,
  height = 280,
  centerFill,
}: PlenaryDonutChartProps) {
  const chartReady = usePlenaryChartReady();
  const theme = useTheme();

  const total = data.reduce(
    (sum, item) => sum + item.value,
    0,
  );

  const donutInnerRadius = 56;
  const donutOuterRadius = 96;
  const centerCircleRadius = 58;

  const resolvedCenterFill =
    centerFill ??
    (theme.palette.mode === "dark"
      ? alpha(theme.palette.primary.main, 0.28)
      : "#b9d7f2");

  function getLabelColor(
    sliceColor: string,
    isSmallSlice: boolean,
  ): string {
    if (isSmallSlice) {
      return theme.palette.text.primary;
    }

    const color = sliceColor.replace("#", "");

    if (color.length !== 6) {
      return "#ffffff";
    }

    const r = Number.parseInt(color.slice(0, 2), 16);
    const g = Number.parseInt(color.slice(2, 4), 16);
    const b = Number.parseInt(color.slice(4, 6), 16);

    const brightness =
      (r * 299 + g * 587 + b * 114) / 1000;

    return brightness > 170
      ? theme.palette.text.primary
      : "#ffffff";
  }

  if (!chartReady) {
    return (
      <Box
        sx={{
          height,
          width: "100%",
        }}
      />
    );
  }

  return (
    <Box
      sx={{
        height,
        width: "100%",
      }}
    >
      <ResponsiveContainer
        width="100%"
        height="100%"
        minWidth={0}
      >
        <PieChart>
          <Pie
            data={data}
            dataKey="value"
            nameKey="label"
            cx="50%"
            cy="56%"
            innerRadius={donutInnerRadius}
            outerRadius={donutOuterRadius}
            startAngle={90}
            endAngle={-270}
            stroke="none"
            labelLine={false}
            isAnimationActive={false}
            label={({
              index,
              cx,
              cy,
              midAngle,
              innerRadius,
              outerRadius,
            }: DonutLabelProps) => {
              if (
                index == null ||
                cx == null ||
                cy == null ||
                midAngle == null ||
                innerRadius == null ||
                outerRadius == null
              ) {
                return null;
              }

              const segment = data[index];

              if (!segment) {
                return null;
              }

              const percent =
                total === 0
                  ? 0
                  : segment.value / total;

              const isSmallSlice = percent <= 0.12;

              const angleInRadians =
                (-Number(midAngle) * Math.PI) / 180;

              const labelRadius =
                Number(innerRadius) +
                (Number(outerRadius) -
                  Number(innerRadius)) /
                  2;

              const x =
                Number(cx) +
                labelRadius *
                  Math.cos(angleInRadians);

              let y =
                Number(cy) +
                labelRadius *
                  Math.sin(angleInRadians);

              if (isSmallSlice) {
                y += 1;
              }

              const labelText =
                segment.labelText ??
                `${
                  total === 0
                    ? 0
                    : (
                        (segment.value / total) *
                        100
                      ).toFixed(1)
                }%`;

              let rotateAngle = 0;

              if (isSmallSlice) {
                rotateAngle = Number(midAngle);

                if (rotateAngle > 90) {
                  rotateAngle -= 180;
                }

                if (rotateAngle < -90) {
                  rotateAngle -= 30;
                }
              }

              return (
                <text
                  x={x}
                  y={y}
                  fill={getLabelColor(
                    segment.color,
                    isSmallSlice,
                  )}
                  textAnchor="middle"
                  dominantBaseline="middle"
                  fontSize={isSmallSlice ? 10.5 : 11}
                  fontWeight={700}
                  transform={
                    isSmallSlice
                      ? `rotate(${rotateAngle}, ${x}, ${y})`
                      : undefined
                  }
                  style={{
                    pointerEvents: "none",
                  }}
                >
                  {labelText}
                </text>
              );
            }}
          >
            {data.map((segment) => (
              <Cell
                key={segment.label}
                fill={segment.color}
                stroke="none"
              />
            ))}
          </Pie>

          <circle
            cx="50%"
            cy="56%"
            r={centerCircleRadius}
            fill={resolvedCenterFill}
            stroke="none"
          />

          <text
            x="50%"
            y="52%"
            textAnchor="middle"
            dominantBaseline="middle"
            fill={theme.palette.text.secondary}
            fontSize="10"
            fontWeight="500"
          >
            {centerLabel}
          </text>

          <text
            x="50%"
            y="61%"
            textAnchor="middle"
            dominantBaseline="middle"
            fill={theme.palette.text.primary}
            fontSize="20"
            fontWeight="700"
          >
            {centerValue}
          </text>
        </PieChart>
      </ResponsiveContainer>
    </Box>
  );
}