import type { Props } from "./schema";

const joinIds = (...parts: (string | number)[]) =>
  parts.map((part) => String(part).replace(/[_-]/g, (c) => `_${c.charCodeAt(0).toString(16)}_`)).join("-");

const COLORS = ["#2878A8", "#D18B35", "#4D8B68", "#8A6FB0"];
const fmt = (n: number) => Number.isInteger(n) ? n.toLocaleString("ja-JP") : n.toLocaleString("ja-JP", { maximumFractionDigits: 1 });

export default function Template(d: Props) {
  const totals = d.items.map(row => row.values.reduce((a, b) => a + b, 0));
  const grandTotal = totals.reduce((a, b) => a + b, 0);
  const titleLines = titleLinesFor(d.title);
  const subtitleLines = d.subtitle ? wrapLines(d.subtitle, 64) : [];
  const titleY = 70;
  const subtitleY = titleY + titleLines.length * 34 + 8;
  const legendY = subtitleY + subtitleLines.length * 22 + 12;
  const plotY = legendY + 34;
  const plot = { x: 120, y: plotY, w: 1040, h: Math.max(150, 530 - plotY) };
  let x = plot.x;
  const rects: { x: number; y: number; w: number; h: number; item: number; series: number }[] = [];
  const boundaries = [plot.x];
  d.items.forEach((row, item) => {
    const width = plot.w * totals[item] / grandTotal;
    let y = plot.y + plot.h;
    row.values.forEach((value, series) => {
      const height = plot.h * value / totals[item];
      y -= height;
      rects.push({ x, y, w: width, h: height, item, series });
    });
    x += width;
    boundaries.push(x);
  });
  return <section className="asset asset-marimekko">
    <style>{`.asset{font-family:var(--font-sans);color:var(--color-on-surface);background:var(--color-surface);max-width:var(--container-slide);margin:auto;padding:2rem;line-height:1.5;font-size:var(--text-body-sm)}.asset *{box-sizing:border-box}.asset h1{font-size:var(--text-h1);line-height:1.3;margin:0 0 .5rem}.muted{color:var(--color-secondary)}.plot{display:block;width:100%;height:auto}.plot .svg-title,.plot .svg-subtitle{display:none}.legend{display:flex;flex-wrap:wrap;gap:.5rem 1.5rem;margin:1rem 0}.legend span{display:flex;gap:.5rem;align-items:center}.swatch{width:1rem;height:1rem;border-radius:2px}.key{font:600 16px var(--font-mono);fill:var(--color-on-surface)}.ledger{width:100%;border-collapse:collapse;margin-top:1.5rem}.ledger th,.ledger td{text-align:left;padding:.65rem .5rem;border-bottom:1px solid var(--color-outline);font-variant-numeric:tabular-nums}.ledger th{color:var(--color-secondary)}.ledger td:not(:first-child),.ledger th:not(:first-child){text-align:right}.explain{margin-top:1.5rem;padding:1rem;background:var(--color-surface-subtle);border-radius:var(--radius-sm)}@media(max-width:640px){.asset{padding:1rem}.asset h1{font-size:var(--text-h2)}.plot{display:none}.ledger,.ledger tbody,.ledger tr,.ledger td{display:block}.ledger thead{display:none}.ledger tr{padding:.75rem 0;border-bottom:1px solid var(--color-outline)}.ledger td{border:0;padding:.2rem 0}.ledger td:not(:first-child){display:inline-block;text-align:left;margin-right:.75rem}.ledger td:not(:first-child)::before{content:attr(data-label) ": ";color:var(--color-secondary)}}`}</style>
    <header><p className="muted">MARIMEKKO · 市場規模 × 構成比</p><h1>{d.title}</h1>{d.subtitle && <p className="muted">{d.subtitle}</p>}</header>
    <div className="legend">{d.series.map((name, i) => <span key={name}><i className="swatch" style={{ background: COLORS[i] }} />{name}</span>)}</div>
    <svg className="plot" data-layout-still="true" xmlns="http://www.w3.org/2000/svg" width="1280" height="720" viewBox="0 0 1280 720" role="img" aria-label="幅は対象の総量、高さの分割は構成比を示すモザイク図">
      <rect width="1280" height="720" fill="var(--color-surface)" />
      {titleLines.map((line, i) => <text key={i} className="svg-title" x="72" y={titleY + i * 34} fontSize="28" fontWeight="700" fill="var(--color-on-surface)">{line}</text>)}
      {subtitleLines.map((line, i) => <text key={i} className="svg-subtitle" x="72" y={subtitleY + i * 22} fontSize="17" fill="var(--color-secondary)">{line}</text>)}
      {d.series.map((name, i) => <g key={name} transform={`translate(${72 + i * 210} ${legendY})`}><rect width="18" height="18" rx="2" fill={COLORS[i]} /><text x="27" y="15" fontSize="17" fill="var(--color-on-surface)">{name}</text></g>)}
      {rects.map(cell => <rect key={joinIds(cell.item, cell.series)} x={cell.x} y={cell.y} width={cell.w} height={cell.h} fill={COLORS[cell.series]} stroke="var(--color-surface)" strokeWidth="2" />)}
      {d.items.map((_, i) => <text key={i} className="key" x={(boundaries[i] + boundaries[i + 1]) / 2} y={plot.y + plot.h + 36} textAnchor="middle">{String(i + 1).padStart(2, "0")}</text>)}
      <text x="72" y="672" fontSize="16" fill="var(--color-secondary)">幅＝総量　／　各帯の高さ＝構成比　／　番号は下の明細に対応</text>
    </svg>
    <table className="ledger"><thead><tr><th>番号</th><th>対象</th><th>総量（{d.unit}）</th>{d.series.map(name => <th key={name}>{name}</th>)}</tr></thead><tbody>{d.items.map((row, i) => <tr key={row.label}><td>{String(i + 1).padStart(2, "0")}</td><td>{row.label}</td><td>{fmt(totals[i])}</td>{row.values.map((value, j) => <td key={d.series[j]} data-label={d.series[j]}>{fmt(value)} · {fmt(value / totals[i] * 100)}%</td>)}</tr>)}</tbody></table>
    <p className="explain">幅は対象ごとの総量に比例し、各対象の内部は構成比100%に正規化しています。幅が小さい対象の細かな値は表で確認してください。</p>
    <footer className="muted">合計の差を保ったまま、構成の違いを比較するための図です。架空のサンプルデータを使用しています。</footer>
  </section>;
}

function titleLinesFor(title: string) {
  return wrapLines(title, 34);
}

function wrapLines(text: string, width: number) {
  return Array.from({ length: Math.ceil([...text].length / width) }, (_, i) => [...text].slice(i * width, (i + 1) * width).join(""));
}
