import { useMemo } from "react";
import {
  Chart as ChartJS,
  CategoryScale,
  LinearScale,
  LineController,
  LineElement,
  PointElement,
  Tooltip,
  type ChartOptions,
  type ChartData,
} from "chart.js";
import { Chart } from "react-chartjs-2";
import { useThemeVars } from "@/lib/theme-provider";
import {
  FALLBACK_TICK,
  FALLBACK_PRIMARY,
  FALLBACK_BG,
  ChartLegendItem,
  formatCount,
  formatChartDateLabel,
  formatTooltipDate,
} from "./chart-shared";
import { Card, CardContent, CardHeader, CardTitle } from "./card";
import { Empty, EmptyDescription } from "./empty";
import { cn } from "@/lib/utils";

ChartJS.register(
  CategoryScale,
  LinearScale,
  LineController,
  LineElement,
  PointElement,
  Tooltip,
);

/**
 * EmailEngagementChart — WealthX DS
 *
 * A three-series daily line chart (Delivered / Opened / Clicked) for the Email
 * Marketing section — mirrors GoHighLevel's "Engagement Analysis" chart. Used
 * on the Email Marketing Overview tab and (later) the per-campaign statistics
 * screen.
 *
 * `Delivered` uses the tenant brand-primary colour; `Opened` and `Clicked` use
 * intentionally-fixed complementary colours so the three series stay legible
 * regardless of tenant theme (same rationale as the fixed severity colours).
 */

/** Opened line colour — fixed blue for series distinction. */
const OPENED_COLOR = "#3B82F6";
/** Clicked line colour — fixed amber for series distinction. */
const CLICKED_COLOR = "#F59E0B";

export interface EmailEngagementPoint {
  /** ISO date string e.g. "2026-07-15" */
  x: string;
  delivered: number;
  opened: number;
  clicked: number;
}

export interface EmailEngagementChartProps {
  data: EmailEngagementPoint[];
  title?: string;
  /** Chart canvas height in pixels */
  height?: number;
  width?: number | string;
  className?: string;
  /** Show or hide the legend */
  showLegend?: boolean;
}

export function EmailEngagementChart({
  data: points,
  title = "Engagement",
  height = 240,
  width = "100%",
  className,
  showLegend = true,
}: EmailEngagementChartProps) {
  const themeVars = useThemeVars();
  const deliveredColor =
    (themeVars["--theme-primary"] as string | undefined) || FALLBACK_PRIMARY;
  const fontFamily =
    (themeVars["--font-sans"] as string | undefined) || "Figtree, sans-serif";

  const hasData = Array.isArray(points) && points.length > 0;

  const series = useMemo(
    () => [
      { key: "delivered" as const, label: "Delivered", color: deliveredColor },
      { key: "opened" as const, label: "Opened", color: OPENED_COLOR },
      { key: "clicked" as const, label: "Clicked", color: CLICKED_COLOR },
    ],
    [deliveredColor],
  );

  // Indices to show on x-axis (max ~6 ticks)
  const tickIndices = useMemo<Set<number>>(() => {
    if (!hasData) return new Set();
    const count = points.length;
    const step = Math.max(1, Math.floor(count / 6));
    const indices = new Set<number>();
    for (let i = 0; i < count; i += step) indices.add(i);
    indices.add(count - 1);
    return indices;
  }, [hasData, points]);

  const data = useMemo<ChartData<"line">>(() => {
    if (!hasData) return { labels: [], datasets: [] };
    return {
      labels: points.map((p) => p.x),
      datasets: series.map((s) => ({
        label: s.label,
        data: points.map((p) => p[s.key]),
        fill: false,
        borderColor: s.color,
        backgroundColor: "transparent",
        borderWidth: 2,
        tension: 0.4,
        pointRadius: 0,
        pointHoverRadius: 5,
        pointHoverBackgroundColor: FALLBACK_BG,
        pointHoverBorderColor: s.color,
        pointHoverBorderWidth: 3,
        pointHitRadius: 10,
      })),
    };
  }, [hasData, points, series]);

  const options = useMemo<ChartOptions<"line">>(
    () => ({
      responsive: true,
      maintainAspectRatio: false,
      animation: { duration: 800, easing: "easeOutQuart" },
      plugins: {
        legend: { display: false },
        tooltip: {
          enabled: true,
          mode: "index",
          intersect: false,
          displayColors: true,
          padding: 12,
          cornerRadius: 0,
          titleFont: { size: 11, weight: 600, family: fontFamily },
          bodyFont: { size: 12, weight: 500, family: fontFamily },
          callbacks: {
            title: (items) => {
              const iso = items[0]?.label;
              return iso ? formatTooltipDate(iso, "daily") : "";
            },
            label: (ctx) =>
              ` ${ctx.dataset.label}: ${formatCount((ctx.parsed.y ?? 0))}`,
          },
        },
      },
      interaction: { mode: "index", intersect: false },
      scales: {
        x: {
          type: "category",
          grid: { display: false },
          border: { display: false },
          ticks: {
            autoSkip: false,
            maxRotation: 0,
            minRotation: 0,
            color: FALLBACK_TICK,
            font: { size: 12, family: fontFamily },
            callback: function (_, index) {
              if (!tickIndices.has(index) || !hasData) return "";
              return formatChartDateLabel(points[index].x);
            },
          },
        },
        y: {
          position: "left",
          grid: { display: false },
          border: { display: false },
          ticks: {
            beginAtZero: true,
            maxTicksLimit: 5,
            padding: 8,
            color: FALLBACK_TICK,
            font: { size: 12, family: fontFamily },
            callback: (v) => formatCount(Number(v)),
          },
        },
      },
    }),
    [tickIndices, hasData, points, fontFamily],
  );

  return (
    <Card
      className={cn("w-full gap-2 py-4 sm:py-6", className)}
      style={{ maxWidth: width, fontFamily }}
    >
      {title && (
        <CardHeader className="px-3 sm:px-6">
          <CardTitle className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
            {title}
          </CardTitle>
        </CardHeader>
      )}
      <CardContent className="px-3 sm:px-6">
        {!hasData ? (
          <Empty className="flex-none p-4" style={{ height }}>
            <EmptyDescription>No engagement data yet</EmptyDescription>
          </Empty>
        ) : (
          <div className="flex flex-col gap-3">
            <div style={{ height, width: "100%", position: "relative" }}>
              <Chart
                key={deliveredColor}
                type="line"
                data={data}
                options={options}
                aria-label={title}
              />
            </div>
            {showLegend && (
              <div className="flex flex-wrap items-center gap-x-4 gap-y-1.5">
                {series.map((s) => (
                  <ChartLegendItem
                    key={s.key}
                    label={s.label}
                    color={s.color}
                    lineStyle="solid"
                  />
                ))}
              </div>
            )}
          </div>
        )}
      </CardContent>
    </Card>
  );
}
