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

const fmt = (n: number) => Number.isInteger(n) ? n.toLocaleString("ja-JP") : n.toLocaleString("ja-JP", { maximumFractionDigits: 2 });
function wrap(text: string, width: number) {
  return Array.from({ length: Math.ceil([...text].length / width) }, (_, i) => [...text].slice(i * width, (i + 1) * width).join(""));
}

export default function Template(d: Props) {
  const titleLines = wrap(d.title, 54);
  const subtitleLines = d.subtitle ? wrap(d.subtitle, 80) : [];
  const titleY = 48;
  const subtitleY = titleY + titleLines.length * 26 + 5;
  const infoY = subtitleY + subtitleLines.length * 18 + 18;
  const chartY = infoY + 30;
  const rowH = 25;
  const axisY = chartY + d.studies.length * rowH + 18;
  const pooledY = axisY + 62;
  const plot = { x: 350, w: 820 };
  const bounds = [d.nullValue, ...d.studies.flatMap(row => [row.lower, row.upper]), d.pooled.lower, d.pooled.upper];
  let min = Math.min(...bounds);
  let max = Math.max(...bounds);
  if (max === min) { const pad = Math.max(1, Math.abs(min) * 0.1); min -= pad; max += pad; }
  const pad = (max - min) * 0.06;
  min -= pad;
  max += pad;
  const x = (v: number) => plot.x + (v - min) / (max - min) * plot.w;
  const maxWeight = Math.max(...d.studies.map(study => study.weight));
  const pooledRadius = 12;
  const ticks = Array.from({ length: 5 }, (_, i) => min + (max - min) * i / 4);

  return <section className="forest">
    <style>{`.forest{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)}.forest *{box-sizing:border-box}.forest h1{font-size:var(--text-h2);line-height:1.3;margin:0}.muted{color:var(--color-secondary)}.plot{display:block;width:100%;height:auto}.plot .svg-title,.plot .svg-subtitle{display:none}.forest-table{width:100%;border-collapse:collapse;margin-top:1.5rem;font-variant-numeric:tabular-nums}.forest-table th,.forest-table td{padding:.65rem .55rem;border-bottom:1px solid var(--color-outline);text-align:right;overflow-wrap:anywhere}.forest-table th{color:var(--color-secondary)}.forest-table th:first-child,.forest-table td:first-child{text-align:left}.pooled{font-weight:700;background:var(--color-surface-subtle)}.notes{margin-top:1rem;padding:1rem;border-left:.25rem solid var(--color-tertiary);background:var(--color-surface-subtle)}@media(max-width:640px){.forest{padding:1rem}.forest h1{font-size:var(--text-h3)}.plot{display:none}.forest-table,.forest-table tbody,.forest-table tr,.forest-table td{display:block}.forest-table thead{display:none}.forest-table tr{padding:.75rem 0;border-bottom:1px solid var(--color-outline)}.forest-table td{border:0;padding:.2rem 0;text-align:left!important}.forest-table td:not(:first-child){display:inline-block;margin-right:.7rem}.forest-table td:not(:first-child)::before{content:attr(data-label) ": ";color:var(--color-secondary)}}`}</style>
    <header><p className="muted">META-ANALYSIS · {d.intervalLabel}</p>
      <h1>{titleLines.map((line, i) => <span key={i}>{line}{i + 1 < titleLines.length && <br />}</span>)}</h1>
      {d.subtitle && <p className="muted">{d.subtitle}</p>}
    </header>
    <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={`title-${i}`} className="svg-title" x="64" y={titleY + i * 26} fontSize="21" fontWeight="700" fill="var(--color-on-surface)">{line}</text>)}
      {subtitleLines.map((line, i) => <text key={`subtitle-${i}`} className="svg-subtitle" x="64" y={subtitleY + i * 18} fontSize="14" fill="var(--color-secondary)">{line}</text>)}
      <text x="64" y={infoY} fontSize="14" fill="var(--color-secondary)">{d.effectMeasure}（{d.unit}） · ● 研究推定値（面積は重み） · ◆ 統合推定 · 破線＝効果なし</text>
      <line x1={x(d.nullValue)} y1={chartY - 12} x2={x(d.nullValue)} y2={axisY} stroke="var(--color-outline)" strokeWidth="2" strokeDasharray="7 6" />
      {d.studies.map((study, i) => {
        const cy = chartY + i * rowH + rowH / 2;
        const radius = Math.sqrt(study.weight / maxWeight) * 10;
        return <g key={study.label}>
          <text x="64" y={cy + 5} fontSize="15" fill="var(--color-on-surface)">{study.label}</text>
          <line x1={x(study.lower)} y1={cy} x2={x(study.upper)} y2={cy} stroke="var(--color-tertiary)" strokeWidth="3" />
          <line x1={x(study.lower)} y1={cy - 5} x2={x(study.lower)} y2={cy + 5} stroke="var(--color-tertiary)" strokeWidth="2" />
          <line x1={x(study.upper)} y1={cy - 5} x2={x(study.upper)} y2={cy + 5} stroke="var(--color-tertiary)" strokeWidth="2" />
          <circle cx={x(study.estimate)} cy={cy} r={radius} fill="var(--color-tertiary)" />
        </g>;
      })}
      {ticks.map((tick, i) => <g key={i}><line x1={x(tick)} y1={axisY - 4} x2={x(tick)} y2={axisY + 4} stroke="var(--color-outline)" /><text x={x(tick)} y={axisY + 22} textAnchor="middle" fontSize="13" fill="var(--color-secondary)">{fmt(tick)}</text></g>)}
      <line x1={plot.x} y1={axisY} x2={plot.x + plot.w} y2={axisY} stroke="var(--color-outline)" />
      <text x="64" y={pooledY + 5} fontSize="16" fontWeight="700" fill="var(--color-on-surface)">統合推定</text>
      <line x1={x(d.pooled.lower)} y1={pooledY} x2={x(d.pooled.upper)} y2={pooledY} stroke="var(--color-on-surface)" strokeWidth="4" />
      <path d={`M ${x(d.pooled.estimate)} ${pooledY - pooledRadius} L ${x(d.pooled.estimate) + pooledRadius} ${pooledY} L ${x(d.pooled.estimate)} ${pooledY + pooledRadius} L ${x(d.pooled.estimate) - pooledRadius} ${pooledY} Z`} fill="var(--color-on-surface)" />
      <text x="64" y="690" fontSize="13" fill="var(--color-secondary)">区間が破線（効果なし）をまたぐ場合は、その研究だけで方向を確定できません。</text>
    </svg>
    <table className="forest-table"><thead><tr><th>研究</th><th>推定値</th><th>{d.intervalLabel}</th><th>重み</th></tr></thead><tbody>
      {d.studies.map(study => <tr key={study.label} data-study-row><td>{study.label}</td><td data-label="推定値">{fmt(study.estimate)} {d.unit}</td><td data-label={d.intervalLabel}>{fmt(study.lower)}〜{fmt(study.upper)} {d.unit}</td><td data-label="重み">{fmt(study.weight)}%</td></tr>)}
      <tr className="pooled"><td>統合推定</td><td data-label="推定値">{fmt(d.pooled.estimate)} {d.unit}</td><td data-label={d.intervalLabel}>{fmt(d.pooled.lower)}〜{fmt(d.pooled.upper)} {d.unit}</td><td data-label="重み">—</td></tr>
    </tbody></table>
    <p className="notes">この図は入力された推定値・区間・重みを描画します。統合方法の妥当性や因果関係を検証するものではありません。無効果の基準値は {fmt(d.nullValue)} {d.unit} です。</p>
  </section>;
}
