// Grouped bar chart — ported from the "Money in vs. money out, by year"
// figure in the original design prototype: same bar mark spec (rounded
// 4px data ends via the same SVG path construction, 2px gap between the
// paired bars, hover tooltip, <details> table view), rebuilt as JSX/state
// instead of the prototype's innerHTML+addEventListener script.
//
// Money VALUES shown as text always go through fmtMoney()/subtractMoney()
// (BigInt-based, CLAUDE.md §2). The one deliberate exception is axis
// geometry: Number() is used below ONLY to size bar heights and gridline
// positions — never to produce a number the user reads — per the Task 8
// brief ("y-axis scaling MAY use Number() ... axis geometry is presentation
// not money arithmetic").

import { useRef, useState, type MouseEvent } from "react";
import { fmtMoney, subtractMoney } from "../lib/money";

export interface YearRow {
  year: number;
  moneyIn: string;
  moneyOut: string;
}

const W = 1000;
const H = 320;
const MARGIN = { t: 14, r: 10, b: 30, l: 52 };

function fmtK(v: number): string {
  return v >= 1000 ? `$${Math.round(v / 1000)}k` : `$${v}`;
}

export function BarsChart({ years }: { years: YearRow[] }) {
  const [hoverIndex, setHoverIndex] = useState<number | null>(null);
  const [tipPos, setTipPos] = useState<{ x: number; y: number }>({ x: 0, y: 0 });
  const figRef = useRef<HTMLElement | null>(null);
  const currentYear = new Date().getFullYear(); // a calendar year label, not money — fine as a JS number

  if (years.length === 0) return null;

  const iw = W - MARGIN.l - MARGIN.r;
  const ih = H - MARGIN.t - MARGIN.b;

  // Axis-geometry-only Number() usage — see file header comment.
  const magnitudes = years.flatMap((row) => [Number(row.moneyIn), Number(row.moneyOut)]);
  const max = Math.max(1, ...magnitudes);
  const top = Math.ceil(max / 100000) * 100000 || 100000;

  const yPos = (v: number) => MARGIN.t + ih - (v / top) * ih;
  const groupW = iw / years.length;
  const barW = Math.min(16, (groupW - 10) / 2);

  function barPath(x: number, value: number): string {
    const r = 4;
    const yy = yPos(Math.max(0, value));
    const h = Math.max(2, MARGIN.t + ih - yy);
    return `M${x},${yy + r} a${r},${r} 0 0 1 ${r},${-r} h${barW - 2 * r} a${r},${r} 0 0 1 ${r},${r} v${h - r} h${-barW} z`;
  }

  function handleMove(index: number, ev: MouseEvent) {
    const fig = figRef.current?.getBoundingClientRect();
    if (!fig) return;
    setHoverIndex(index);
    setTipPos({ x: ev.clientX - fig.left + 14, y: ev.clientY - fig.top - 10 });
  }

  const hoverRow = hoverIndex === null ? null : years[hoverIndex]!;

  return (
    <figure ref={figRef}>
      <svg
        className="chart"
        viewBox={`0 0 ${W} ${H}`}
        role="img"
        aria-label={`Grouped bar chart of yearly money in and out, ${years[0]!.year} to ${years[years.length - 1]!.year}`}
      >
        {[0, 1, 2, 3, 4, 5].map((g) => {
          const v = (top * g) / 5;
          const yy = yPos(v);
          return (
            <g key={g}>
              <line x1={MARGIN.l} y1={yy} x2={W - MARGIN.r} y2={yy} stroke="var(--grid)" strokeWidth={1} />
              <text x={MARGIN.l - 8} y={yy + 4} textAnchor="end" fontSize={11} fill="var(--ink-muted)">
                {fmtK(v)}
              </text>
            </g>
          );
        })}
        {years.map((row, i) => {
          const cx = MARGIN.l + groupW * i + groupW / 2;
          const x1 = cx - barW - 1;
          const x2 = cx + 1;
          const showLabel = i % 2 === 0 || i === years.length - 1;
          return (
            <g
              key={row.year}
              onMouseMove={(ev) => handleMove(i, ev)}
              onMouseLeave={() => setHoverIndex((cur) => (cur === i ? null : cur))}
            >
              <rect x={MARGIN.l + groupW * i} y={MARGIN.t} width={groupW} height={ih} fill="transparent" />
              <path d={barPath(x1, Number(row.moneyIn))} fill="var(--series-1)" />
              <path d={barPath(x2, Number(row.moneyOut))} fill="var(--series-2)" />
              {showLabel && (
                <text x={cx} y={H - 8} textAnchor="middle" fontSize={11} fill="var(--ink-muted)">
                  {row.year}
                </text>
              )}
            </g>
          );
        })}
        <line
          x1={MARGIN.l}
          y1={MARGIN.t + ih}
          x2={W - MARGIN.r}
          y2={MARGIN.t + ih}
          stroke="var(--baseline)"
          strokeWidth={1}
        />
      </svg>
      <div className={`tip${hoverRow ? " visible" : ""}`} style={{ left: tipPos.x, top: tipPos.y }}>
        {hoverRow && (
          <>
            <div className="t">
              {hoverRow.year}
              {hoverRow.year === currentYear ? " (to date)" : ""}
            </div>
            <div className="row">
              <span>Money in</span>
              <b>{fmtMoney(hoverRow.moneyIn)}</b>
            </div>
            <div className="row">
              <span>Money out</span>
              <b>{fmtMoney(hoverRow.moneyOut)}</b>
            </div>
            <div className="row">
              <span>Kept</span>
              <b>{fmtMoney(subtractMoney(hoverRow.moneyIn, hoverRow.moneyOut))}</b>
            </div>
          </>
        )}
      </div>
      <details className="tableview">
        <summary>View as table</summary>
        <table>
          <thead>
            <tr>
              <th>Year</th>
              <th className="num">Money in</th>
              <th className="num">Money out</th>
              <th className="num">Kept</th>
            </tr>
          </thead>
          <tbody>
            {years.map((row) => (
              <tr key={row.year}>
                <td>{row.year}</td>
                <td className="num">{fmtMoney(row.moneyIn)}</td>
                <td className="num">{fmtMoney(row.moneyOut)}</td>
                <td className="num">{fmtMoney(subtractMoney(row.moneyIn, row.moneyOut))}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </details>
    </figure>
  );
}
