"use client";

import type { BubbleDataPoint, Chart as ChartType, Point } from "chart.js";
import dynamic from "next/dynamic";
import { useEffect, useRef } from "react";

interface DonutChartProps {
  data: {
    labels: string[];
    values: number[];
    colors?: string[];
  };
  centerText?: {
    title?: string;
    value?: string | number;
  };
}

function DonutChartSkeleton() {
  return (
    <div className="flex items-center justify-center h-[300px]">
      <div className="animate-pulse flex items-center gap-8">
        <div className="w-40 h-40 rounded-full bg-gray-200 dark:bg-gray-700" />
        <div className="space-y-2">
          {[...Array(4)].map((_, i) => (
            <div key={i} className="flex items-center gap-2">
              <div className="w-3 h-3 rounded-full bg-gray-200 dark:bg-gray-700" />
              <div className="w-20 h-3 rounded bg-gray-200 dark:bg-gray-700" />
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

function DonutChartInner({ data, centerText }: DonutChartProps) {
  const ref = useRef<HTMLCanvasElement | null>(null);
  const chartRef = useRef<ChartType<"doughnut"> | null>(null);

  useEffect(() => {
    let isMounted = true;

    async function initChart() {
      if (!ref.current || !data.values.length) return;

      const ctx = ref.current.getContext("2d");
      if (!ctx) return;

      const { default: Chart } = await import("chart.js/auto");

      if (!isMounted) return;

      // Default colors if not provided
      const defaultColors: string[] = [
        "rgba(59, 130, 246, 0.8)", // blue
        "rgba(16, 185, 129, 0.8)", // green
        "rgba(249, 115, 22, 0.8)", // orange
        "rgba(236, 72, 153, 0.8)", // pink
        "rgba(139, 92, 246, 0.8)", // purple
        "rgba(107, 114, 128, 0.8)", // gray
      ];

      const colors: string[] = data.colors || defaultColors;

      // Helper to create an array of colors based on the data length
      const getColors = () => {
        const result: string[] = [];
        for (let i = 0; i < data.values.length; i++) {
          result.push(colors[i % colors.length]);
        }
        return result;
      };

      // Destroy existing chart if any
      if (chartRef.current) {
        chartRef.current.destroy();
      }

      chartRef.current = new Chart(ctx, {
        type: "doughnut",
        data: {
          labels: data.labels,
          datasets: [
            {
              data: data.values,
              backgroundColor: getColors(),
              borderWidth: 1,
              hoverOffset: 5,
            },
          ],
        },
        options: {
          responsive: true,
          maintainAspectRatio: true,
          cutout: "70%",
          plugins: {
            legend: {
              position: "right",
              labels: {
                boxWidth: 12,
                padding: 20,
                usePointStyle: true,
              },
            },
            tooltip: {
              callbacks: {
                label: (context) => {
                  const label = context.label || "";
                  const value = context.formattedValue;
                  const total = context.chart.data.datasets[0].data.reduce(
                    (
                      a: number,
                      b:
                        | number
                        | Point
                        | [number, number]
                        | BubbleDataPoint
                        | null
                    ) => {
                      if (typeof b === "number") {
                        return a + b;
                      }
                      return a;
                    },
                    0
                  ) as number;
                  const percentage = Math.round((context.parsed * 100) / total);
                  return `${label}: ${value} (${percentage}%)`;
                },
              },
            },
          },
        },
        plugins: centerText
          ? [
              {
                id: "centerText",
                beforeDraw: (chart: ChartType<"doughnut">) => {
                  const height = chart.height;
                  const ctx = chart.ctx;
                  ctx.restore();

                  const chartArea = chart.chartArea;
                  const chartWidth = chartArea.right - chartArea.left;
                  const centerX = chartArea.left + chartWidth / 2;
                  const centerY = height / 2;

                  if (centerText.title) {
                    ctx.font = "1rem sans-serif";
                    ctx.fillStyle = "#6B7280";
                    ctx.textAlign = "center";
                    ctx.textBaseline = "middle";
                    ctx.fillText(centerText.title, centerX, centerY - 10);
                  }

                  if (centerText.value !== undefined) {
                    ctx.font = "bold 1.5rem sans-serif";
                    ctx.fillStyle = "#1F2937";
                    ctx.textAlign = "center";
                    ctx.textBaseline = "middle";
                    ctx.fillText(
                      centerText.value.toString(),
                      centerX,
                      centerY + 15
                    );
                  }
                  ctx.save();
                },
              },
            ]
          : [],
      });
    }

    initChart();

    return () => {
      isMounted = false;
      if (chartRef.current) {
        chartRef.current.destroy();
        chartRef.current = null;
      }
    };
  }, [data, centerText]);

  return <canvas ref={ref} height={300} />;
}

const DonutChart = dynamic(() => Promise.resolve(DonutChartInner), {
  ssr: false,
  loading: () => <DonutChartSkeleton />,
});

export default DonutChart;
