import React, { useMemo, useState } from "react";
import {
  Chart as ChartJS,
  CategoryScale,
  LinearScale,
  BarController,
  BarElement,
  Tooltip,
  type ChartOptions,
  type ChartData,
} from "chart.js";
import { Chart } from "react-chartjs-2";
import { useThemeVars } from "@/lib/theme-provider";
import { Card, CardContent, CardHeader, CardTitle, CardAction } from "./card";
import { Empty, EmptyDescription } from "./empty";
import { Skeleton } from "./skeleton";
import { cn } from "@/lib/utils";
import {
  FALLBACK_TICK,
  SEVERITY_COLORS,
  formatTooltipDate,
  formatMonthLabel,
  formatCount,
  ChartLegendItem,
  ChartPeriodButton,
} from "./chart-shared";

ChartJS.register(
  CategoryScale,
  LinearScale,
  BarController,
  BarElement,
  Tooltip,
);

// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------

export interface AlertHistoryDataPoint {
  /** ISO date string e.g. "2024-01-01" */
  date: string;
  /** Count of high-severity alerts */
  high: number;
  /** Count of medium-severity alerts */
  medium: number;
  /** Count of low-severity alerts */
  low: number;
}

export type AlertHistoryPeriod = 3 | 6 | 12;

export interface BackofficeAlertHistoryChartProps {
  chartData?: AlertHistoryDataPoint[] | null;
  title?: string;
  /** Show or hide the chart legend */
  showLegend?: boolean;
  /** Legend placement relative to the chart */
  legendPosition?: "top" | "bottom";
  /** Show or hide X axis labels */
  showXAxis?: boolean;
  /** Show or hide Y axis labels */
  showYAxis?: boolean;
  /** Default period selector value */
  defaultPeriod?: AlertHistoryPeriod;
  /** Chart canvas height in pixels */
  height?: number;
  /** Card max-width in pixels or CSS string */
  width?: number | string;
  className?: string;
  /** Show skeleton loading state instead of the chart */
  isLoading?: boolean;
}

// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------

const ALERT_PERIODS: AlertHistoryPeriod[] = [3, 6, 12];
const SLICE_COUNT: Record<AlertHistoryPeriod, number> = { 3: 3, 6: 6, 12: 12 };

// ---------------------------------------------------------------------------
// Legend
// ---------------------------------------------------------------------------

function ChartLegend() {
  return (
    <div className="flex flex-wrap gap-x-3 gap-y-1.5 pb-2">
      <ChartLegendItem label="High" color={SEVERITY_COLORS.high} />
      <ChartLegendItem label="Medium" color={SEVERITY_COLORS.medium} />
      <ChartLegendItem label="Low" color={SEVERITY_COLORS.low} />
    </div>
  );
}

// ---------------------------------------------------------------------------
// Component
// ---------------------------------------------------------------------------

export function BackofficeAlertHistoryChart({
  chartData,
  title = "Alert History",
  showLegend = true,
  legendPosition = "top",
  showXAxis = true,
  showYAxis = false,
  defaultPeriod = 6,
  height = 200,
  width = "100%",
  className,
  isLoading = false,
}: BackofficeAlertHistoryChartProps) {
  const [period, setPeriod] = useState<AlertHistoryPeriod>(defaultPeriod);

  const themeVars = useThemeVars();
  const fontFamily: string =
    (themeVars["--font-sans"] as string | undefined) || "Figtree, sans-serif";

  const sliced = useMemo<AlertHistoryDataPoint[] | null>(() => {
    if (!chartData?.length) return null;
    const count = Math.min(SLICE_COUNT[period], chartData.length);
    return chartData.slice(chartData.length - count);
  }, [chartData, period]);

  const labels = useMemo(
    () => sliced?.map((p) => formatMonthLabel(p.date)) ?? [],
    [sliced],
  );

  const data = useMemo<ChartData<"bar">>(() => {
    if (!sliced) return { labels: [], datasets: [] };
    return {
      labels,
      datasets: [
        {
          label: "High",
          data: sliced.map((p) => p.high),
          backgroundColor: SEVERITY_COLORS.high,
          borderWidth: 0,
          stack: "alerts",
        },
        {
          label: "Medium",
          data: sliced.map((p) => p.medium),
          backgroundColor: SEVERITY_COLORS.medium,
          borderWidth: 0,
          stack: "alerts",
        },
        {
          label: "Low",
          data: sliced.map((p) => p.low),
          backgroundColor: SEVERITY_COLORS.low,
          borderWidth: 0,
          stack: "alerts",
        },
      ],
    };
  }, [sliced, labels]);

  const options = useMemo<ChartOptions<"bar">>(
    () => ({
      responsive: true,
      maintainAspectRatio: false,
      animation: { duration: 600, easing: "easeOutQuart" },
      layout: { padding: 0 },
      plugins: {
        legend: { display: false },
        tooltip: {
          mode: "index",
          intersect: false,
          padding: 12,
          cornerRadius: 0,
          titleFont: { size: 11, weight: 600 },
          bodyFont: { size: 12, weight: 500 },
          callbacks: {
            title: (tooltipItems) => {
              const idx = tooltipItems[0]?.dataIndex;
              if (idx != null && sliced?.[idx]?.date) {
                return formatTooltipDate(sliced[idx].date, "monthly");
              }
              return tooltipItems[0]?.label ?? "";
            },
            label: (ctx) => {
              const val = ctx.raw as number;
              if (val === 0) return;
              return ` ${ctx.dataset.label}: ${formatCount(val)}`;
            },
          },
        },
      },
      scales: {
        x: {
          stacked: true,
          display: showXAxis,
          grid: { display: false },
          border: { display: false },
          ticks: {
            maxRotation: 0,
            minRotation: 0,
            color: FALLBACK_TICK,
            font: { size: 10 },
          },
        },
        y: {
          stacked: true,
          display: showYAxis,
          grid: { display: false },
          border: { display: false },
          ticks: {
            padding: 8,
            maxTicksLimit: 5,
            color: FALLBACK_TICK,
            font: { size: 10 },
            callback: (v) => formatCount(Number(v)),
          },
        },
      },
    }),
    [showXAxis, showYAxis, sliced],
  );

  return (
    <Card
      className={cn("w-full py-4 sm:py-6 gap-2", className)}
      style={{ maxWidth: width, fontFamily }}
    >
      <CardHeader className="px-3 sm:px-6">
        <CardTitle className="text-xs font-semibold uppercase tracking-wide">
          {title}
        </CardTitle>
        <CardAction>
          <div className="flex gap-0.5 sm:gap-1">
            {ALERT_PERIODS.map((p) => (
              <ChartPeriodButton
                key={p}
                period={p}
                active={period === p}
                onClick={() => setPeriod(p)}
              />
            ))}
          </div>
        </CardAction>
      </CardHeader>

      <CardContent className="px-3 sm:px-6">
        {isLoading ? (
          <Skeleton style={{ height, width: "100%" }} />
        ) : !sliced ? (
          <Empty className="flex-none p-4" style={{ height }}>
            <EmptyDescription>No data available</EmptyDescription>
          </Empty>
        ) : (
          <div className="flex flex-col gap-2">
            {showLegend && legendPosition === "top" && <ChartLegend />}
            <div style={{ height, width: "100%", position: "relative" }}>
              <Chart
                type="bar"
                data={data}
                options={options}
                aria-label={title}
              />
            </div>
            {showLegend && legendPosition === "bottom" && <ChartLegend />}
          </div>
        )}
      </CardContent>
    </Card>
  );
}
