"use client";

import { useState, useRef } from "react";
import { cn } from "@/lib/utils";

export type TimeSeriesPoint = { date: string; value: number };

/** "day" expects "YYYY-MM-DD", "month" expects "YYYY-MM" — kept as a plain
 *  string enum rather than a formatter function prop, since this chart is
 *  a "use client" component and functions passed from a server component
 *  parent aren't serializable across that boundary (React throws: "Functions
 *  cannot be passed directly to Client Components"). */
function formatPoint(date: string, kind: "day" | "month"): string {
  if (kind === "month") {
    const [y, m] = date.split("-");
    return new Date(Number(y), Number(m) - 1, 1).toLocaleDateString(undefined, { month: "short", year: "2-digit" });
  }
  return new Date(`${date}T00:00:00Z`).toLocaleDateString(undefined, { month: "short", day: "numeric", timeZone: "UTC" });
}

/** Single-series area/line chart with a hover crosshair+tooltip and a
 *  table-view fallback — hand-rolled SVG, no charting lib. */
export function TimeSeriesChart({
  data,
  formatValue = (n) => String(n),
  dateFormat = "day",
  height = 200,
}: {
  data: TimeSeriesPoint[];
  formatValue?: (n: number) => string;
  dateFormat?: "day" | "month";
  height?: number;
}) {
  const [hovered, setHovered] = useState<number | null>(null);
  const [showTable, setShowTable] = useState(false);
  const svgRef = useRef<SVGSVGElement>(null);
  const formatDate = (d: string) => formatPoint(d, dateFormat);

  const width = 600;
  const paddingBottom = 24;
  const paddingTop = 12;
  const plotHeight = height - paddingBottom - paddingTop;
  const max = Math.max(1, ...data.map((d) => d.value));
  const n = data.length;

  if (n === 0) {
    return <p className="text-sm text-muted-foreground py-8 text-center">No data yet.</p>;
  }

  const xFor = (i: number) => (n === 1 ? width / 2 : (i / (n - 1)) * width);
  const yFor = (v: number) => height - paddingBottom - (v / max) * plotHeight;

  const linePath = data.map((d, i) => `${i === 0 ? "M" : "L"} ${xFor(i)} ${yFor(d.value)}`).join(" ");
  const areaPath = `${linePath} L ${xFor(n - 1)} ${height - paddingBottom} L ${xFor(0)} ${height - paddingBottom} Z`;

  function handleMove(e: React.MouseEvent<SVGSVGElement>) {
    const svg = svgRef.current;
    if (!svg) return;
    const rect = svg.getBoundingClientRect();
    const relX = (e.clientX - rect.left) / rect.width;
    const i = Math.round(relX * (n - 1));
    setHovered(Math.max(0, Math.min(n - 1, i)));
  }

  const labelStep = Math.max(1, Math.ceil(n / 6));

  return (
    <div className="space-y-2">
      {showTable ? (
        <div className="overflow-x-auto max-h-64">
          <table className="w-full text-sm">
            <thead>
              <tr className="border-b text-left text-muted-foreground sticky top-0 bg-card">
                <th className="py-1.5 pr-4 font-medium">Date</th>
                <th className="py-1.5 pr-4 font-medium">Value</th>
              </tr>
            </thead>
            <tbody>
              {data.map((d) => (
                <tr key={d.date} className="border-b last:border-0">
                  <td className="py-1.5 pr-4">{formatDate(d.date)}</td>
                  <td className="py-1.5 pr-4 tabular-nums">{formatValue(d.value)}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      ) : (
        <div className="relative">
          <svg
            ref={svgRef}
            viewBox={`0 0 ${width} ${height}`}
            className="w-full h-auto"
            onMouseMove={handleMove}
            onMouseLeave={() => setHovered(null)}
          >
            <line x1={0} y1={height - paddingBottom} x2={width} y2={height - paddingBottom} stroke="var(--border)" strokeWidth={1} />
            <path d={areaPath} fill="var(--chart-1)" opacity={0.15} />
            <path d={linePath} fill="none" stroke="var(--chart-1)" strokeWidth={2} />
            {data.map((d, i) => (
              i % labelStep === 0 && (
                <text key={i} x={xFor(i)} y={height - paddingBottom + 15} textAnchor="middle" fontSize={10} fill="var(--muted-foreground)">
                  {formatDate(d.date)}
                </text>
              )
            ))}
            {hovered !== null && (
              <>
                <line x1={xFor(hovered)} y1={paddingTop} x2={xFor(hovered)} y2={height - paddingBottom} stroke="var(--border)" strokeWidth={1} strokeDasharray="3 3" />
                <circle cx={xFor(hovered)} cy={yFor(data[hovered]!.value)} r={4} fill="var(--chart-1)" stroke="var(--card)" strokeWidth={2} />
              </>
            )}
          </svg>
          {hovered !== null && (
            <div
              className="pointer-events-none absolute top-0 -translate-x-1/2 rounded-md border bg-popover px-2 py-1 text-xs shadow-md whitespace-nowrap"
              style={{ left: `${(xFor(hovered) / width) * 100}%` }}
            >
              <p className="font-medium text-popover-foreground">{formatDate(data[hovered]!.date)}</p>
              <p className="text-muted-foreground">{formatValue(data[hovered]!.value)}</p>
            </div>
          )}
        </div>
      )}

      <button
        type="button"
        onClick={() => setShowTable((s) => !s)}
        className={cn("text-xs text-muted-foreground hover:text-foreground transition-colors underline underline-offset-2")}
      >
        {showTable ? "Show chart" : "Show as table"}
      </button>
    </div>
  );
}
