import type { ChartSpec } from "../lib/chartspec";

// ChartView：把 chart spec 自绘成 SVG（bar / line / pie），无第三方图表依赖。
const PALETTE = ["#60a5fa", "#34d399", "#fbbf24", "#f87171", "#a78bfa", "#22d3ee", "#fb923c", "#4ade80"];

export function ChartView({ spec }: { spec: ChartSpec }) {
  return (
    <figure className="my-2 rounded-lg border border-line bg-ink-950/50 p-3">
      {spec.title && <figcaption className="mb-2 text-[12px] font-medium text-slate-200">{spec.title}</figcaption>}
      {spec.type === "pie" ? <Pie spec={spec} /> : <BarLine spec={spec} />}
      {spec.type !== "pie" && spec.series.length > 1 && <Legend names={spec.series.map((s, i) => s.name || `系列${i + 1}`)} />}
    </figure>
  );
}

function Legend({ names }: { names: string[] }) {
  return (
    <div className="mt-2 flex flex-wrap gap-3">
      {names.map((n, i) => (
        <span key={i} className="flex items-center gap-1 text-[10px] text-slate-400">
          <span className="inline-block h-2 w-2 rounded-sm" style={{ background: PALETTE[i % PALETTE.length] }} />
          {n}
        </span>
      ))}
    </div>
  );
}

// BarLine：柱状图 / 折线图（共用坐标系）。
function BarLine({ spec }: { spec: ChartSpec }) {
  const W = 480, H = 220, padL = 40, padB = 28, padT = 8, padR = 8;
  const plotW = W - padL - padR, plotH = H - padT - padB;
  const all = spec.series.flatMap((s) => s.data);
  const max = Math.max(1, ...all);
  const min = Math.min(0, ...all);
  const span = max - min || 1;
  const y = (v: number) => padT + plotH - ((v - min) / span) * plotH;
  const n = spec.labels.length;
  const slot = plotW / n;

  return (
    <svg viewBox={`0 0 ${W} ${H}`} className="w-full" role="img" aria-label={spec.title || "图表"}>
      {/* y 轴基准线 */}
      <line x1={padL} y1={y(min)} x2={W - padR} y2={y(min)} stroke="#334155" strokeWidth={1} />
      <text x={padL - 6} y={y(max)} fill="#64748b" fontSize={9} textAnchor="end">{fmt(max)}</text>
      <text x={padL - 6} y={y(min) + 3} fill="#64748b" fontSize={9} textAnchor="end">{fmt(min)}</text>

      {spec.type === "bar"
        ? spec.series.map((s, si) =>
            s.data.map((v, i) => {
              const bw = (slot * 0.7) / spec.series.length;
              const x = padL + i * slot + slot * 0.15 + si * bw;
              return (
                <rect key={`${si}-${i}`} x={x} y={Math.min(y(v), y(0))} width={bw} height={Math.abs(y(v) - y(0))}
                  fill={PALETTE[si % PALETTE.length]} rx={1}>
                  <title>{`${spec.labels[i]}: ${v}`}</title>
                </rect>
              );
            }),
          )
        : spec.series.map((s, si) => {
            const pts = s.data.map((v, i) => `${padL + i * slot + slot / 2},${y(v)}`).join(" ");
            return (
              <g key={si}>
                <polyline points={pts} fill="none" stroke={PALETTE[si % PALETTE.length]} strokeWidth={2} />
                {s.data.map((v, i) => (
                  <circle key={i} cx={padL + i * slot + slot / 2} cy={y(v)} r={2.5} fill={PALETTE[si % PALETTE.length]}>
                    <title>{`${spec.labels[i]}: ${v}`}</title>
                  </circle>
                ))}
              </g>
            );
          })}

      {/* x 轴标签 */}
      {spec.labels.map((lb, i) => (
        <text key={i} x={padL + i * slot + slot / 2} y={H - padB + 14} fill="#64748b" fontSize={9} textAnchor="middle">
          {lb.length > 6 ? lb.slice(0, 6) + "…" : lb}
        </text>
      ))}
    </svg>
  );
}

// Pie：饼图（用第一条系列）。
function Pie({ spec }: { spec: ChartSpec }) {
  const data = spec.series[0]?.data ?? [];
  const total = data.reduce((a, b) => a + Math.max(0, b), 0) || 1;
  const cx = 110, cy = 110, r = 90;
  let acc = -Math.PI / 2; // 从 12 点方向起
  const arcs = data.map((v, i) => {
    const frac = Math.max(0, v) / total;
    const a0 = acc;
    const a1 = acc + frac * Math.PI * 2;
    acc = a1;
    const large = a1 - a0 > Math.PI ? 1 : 0;
    const x0 = cx + r * Math.cos(a0), y0 = cy + r * Math.sin(a0);
    const x1 = cx + r * Math.cos(a1), y1 = cy + r * Math.sin(a1);
    const d = `M${cx},${cy} L${x0.toFixed(2)},${y0.toFixed(2)} A${r},${r} 0 ${large} 1 ${x1.toFixed(2)},${y1.toFixed(2)} Z`;
    return { d, color: PALETTE[i % PALETTE.length], label: spec.labels[i], pct: Math.round(frac * 100) };
  });
  return (
    <div className="flex items-center gap-4">
      <svg viewBox="0 0 220 220" className="h-44 w-44 shrink-0" role="img" aria-label={spec.title || "饼图"}>
        {arcs.map((a, i) => (
          <path key={i} d={a.d} fill={a.color} stroke="#0b1220" strokeWidth={1}>
            <title>{`${a.label}: ${data[i]} (${a.pct}%)`}</title>
          </path>
        ))}
      </svg>
      <div className="flex flex-col gap-1">
        {arcs.map((a, i) => (
          <span key={i} className="flex items-center gap-1.5 text-[10px] text-slate-400">
            <span className="inline-block h-2 w-2 rounded-sm" style={{ background: a.color }} />
            {a.label} · {a.pct}%
          </span>
        ))}
      </div>
    </div>
  );
}

function fmt(v: number): string {
  if (Math.abs(v) >= 1000) return (v / 1000).toFixed(1) + "k";
  return String(Math.round(v * 100) / 100);
}
