"use client";

import { useId } from "react";

interface Series {
  label: string;
  color: string;
  points: { date: Date; value: number | null }[];
  formatValue?: (value: number) => string;
}

/**
 * Two real series (Avg. Opportunity Score, Products scored) overlaid on one
 * chart, each normalized to its own min/max so both are visible regardless
 * of unit — a 0-100 score and a raw product count are not comparable on a
 * shared numeric axis, so this deliberately never prints one. The legend
 * names each series and native <title> tooltips on every point carry the
 * real, unnormalized value — nothing here hides or fabricates a number, it
 * only avoids implying a shared scale that doesn't exist.
 */
export function GrowthChart({ series, emptyLabel, height = 220 }: { series: Series[]; emptyLabel: string; height?: number }) {
  const gradientId = useId();
  const width = 720;
  const paddingX = 8;
  const paddingY = 12;

  const prepared = series.map((s) => {
    const valid = s.points.filter((p): p is { date: Date; value: number } => p.value !== null);
    return { ...s, valid };
  });

  const hasEnoughData = prepared.some((s) => s.valid.length >= 2);
  if (!hasEnoughData) {
    return (
      <div className="flex items-center justify-center rounded-lg border border-dashed border-border text-xs text-muted-foreground" style={{ height }}>
        {emptyLabel}
      </div>
    );
  }

  return (
    <div className="flex flex-col gap-3">
      <div className="flex flex-wrap gap-4 text-xs font-medium text-muted-foreground">
        {series.map((s) => (
          <span key={s.label} className="inline-flex items-center gap-1.5">
            <span className="inline-block h-[3px] w-3 rounded-full" style={{ backgroundColor: s.color }} aria-hidden="true" />
            {s.label}
          </span>
        ))}
      </div>

      <div className="relative">
        <svg viewBox={`0 0 ${width} ${height}`} className="w-full" style={{ height }} role="img" aria-label={series.map((s) => s.label).join(" / ")} preserveAspectRatio="none">
          <defs>
            <linearGradient id={gradientId} x1="0" y1="0" x2="0" y2="1">
              <stop offset="0%" stopColor={series[0]?.color} stopOpacity="0.22" />
              <stop offset="100%" stopColor={series[0]?.color} stopOpacity="0" />
            </linearGradient>
          </defs>
          {[0, 0.5, 1].map((f) => (
            <line
              key={f}
              x1={paddingX}
              x2={width - paddingX}
              y1={paddingY + f * (height - paddingY * 2)}
              y2={paddingY + f * (height - paddingY * 2)}
              stroke="var(--border)"
              strokeWidth={1}
            />
          ))}

          {prepared.map((s, seriesIndex) => {
            if (s.valid.length < 2) return null;
            const values = s.valid.map((p) => p.value);
            const min = Math.min(...values);
            const max = Math.max(...values);
            const range = max - min || 1;
            const coords = s.valid.map((p, i) => {
              const x = paddingX + (i / (s.valid.length - 1)) * (width - paddingX * 2);
              const y = height - paddingY - ((p.value - min) / range) * (height - paddingY * 2);
              return { x, y, point: p };
            });
            const polylinePoints = coords.map((c) => `${c.x},${c.y}`).join(" ");
            const last = coords[coords.length - 1];
            const areaPath = `M${paddingX},${height - paddingY} L${polylinePoints.split(" ").join(" L")} L${last.x},${height - paddingY} Z`;
            const fmt = (v: number) => (s.formatValue ? s.formatValue(v) : new Intl.NumberFormat().format(v));

            return (
              <g key={s.label}>
                {seriesIndex === 0 && <path d={areaPath} fill={`url(#${gradientId})`} stroke="none" />}
                <polyline fill="none" stroke={s.color} strokeWidth={2.5} strokeLinejoin="round" points={polylinePoints} />
                {coords.map((c, i) => (
                  <circle key={i} cx={c.x} cy={c.y} r={i === coords.length - 1 ? 3 : 2} fill={s.color}>
                    <title>
                      {s.label} — {c.point.date.toISOString().slice(0, 10)}: {fmt(c.point.value)}
                    </title>
                  </circle>
                ))}
              </g>
            );
          })}
        </svg>
      </div>

      {/* Same accessible-table fallback pattern as MetricChart — see that
          component's comment for why sr-only lives on the wrapping div. */}
      <div className="sr-only">
        {prepared.map((s) => (
          <table key={s.label}>
            <caption>{s.label}</caption>
            <thead>
              <tr>
                <th scope="col">Date</th>
                <th scope="col">Value</th>
              </tr>
            </thead>
            <tbody>
              {s.valid.map((p, i) => (
                <tr key={i}>
                  <td>{p.date.toISOString().slice(0, 10)}</td>
                  <td>{s.formatValue ? s.formatValue(p.value) : p.value}</td>
                </tr>
              ))}
            </tbody>
          </table>
        ))}
      </div>
    </div>
  );
}
