// =====================================================================
// Narrative arc — Task 4
// Shows dramatic-tension curve per act for the focused play (or
// overlay curves for visible plays). Annotated with selected character's
// presence per act.
// =====================================================================

function NarrativeArc({ plays, focusPlay, selectedChar, selectedCharData, hoverChar, themeFilter }) {
  const [wrap, size] = useSize();
  const W = size.w || 720, H = size.h || 200;
  const pad = { l: 56, r: 28, t: 26, b: 38 };
  const iw = W - pad.l - pad.r;
  const ih = H - pad.t - pad.b;

  // smooth curve through points
  function smoothPath(pts) {
    if (pts.length < 2) return "";
    let d = `M ${pts[0][0]} ${pts[0][1]}`;
    for (let i = 0; i < pts.length - 1; i++) {
      const p0 = pts[i-1] || pts[i];
      const p1 = pts[i], p2 = pts[i+1], p3 = pts[i+2] || pts[i+1];
      const cp1x = p1[0] + (p2[0] - p0[0]) / 6;
      const cp1y = p1[1] + (p2[1] - p0[1]) / 6;
      const cp2x = p2[0] - (p3[0] - p1[0]) / 6;
      const cp2y = p2[1] - (p3[1] - p1[1]) / 6;
      d += ` C ${cp1x} ${cp1y}, ${cp2x} ${cp2y}, ${p2[0]} ${p2[1]}`;
    }
    return d;
  }

  if (!plays.length) return null;

  // visible plays curve overlay; focused gets full opacity
  const visible = plays;
  const focused = focusPlay ? plays.find(p => p.id === focusPlay) : null;

  // x by act index normalized (0..1) so plays of different act counts align
  function pts(play) {
    const n = play.tension.length;
    return play.tension.map((v, i) => [
      pad.l + (i / (n - 1)) * iw,
      pad.t + (1 - v) * ih,
    ]);
  }

  return (
    <div className="panel">
      <div className="panel-head">
        <div className="panel-title">
          <span className="num">04</span>叙 事 节 奏 弧 线
        </div>
        <div className="panel-meta">
          DRAMATIC&nbsp;TENSION · {focused ? `${focused.acts.length} ACTS` : `${visible.length} PLAYS OVERLAID`}
        </div>
      </div>
      <div className="panel-body" ref={wrap}>
        <svg width="100%" height="100%" className="no-select">
          {/* y gridlines */}
          {[0, 0.25, 0.5, 0.75, 1].map(v => {
            const y = pad.t + (1 - v) * ih;
            return (
              <g key={v}>
                <line x1={pad.l} y1={y} x2={W - pad.r} y2={y} stroke="var(--ink-3)" strokeWidth="0.5" strokeDasharray={v === 0 || v === 1 ? null : "1 4"} />
                <text x={pad.l - 8} y={y + 3} textAnchor="end" fontSize="9" className="mono label-dim" style={{ letterSpacing: "0.1em" }}>
                  {v === 0 ? "起" : v === 0.25 ? "承" : v === 0.5 ? "" : v === 0.75 ? "转" : "合"}
                </text>
              </g>
            );
          })}
          {/* axis labels */}
          <text x={pad.l - 38} y={pad.t + ih/2 + 4} fontSize="10" className="mono label-dim" textAnchor="middle"
                transform={`rotate(-90, ${pad.l - 38}, ${pad.t + ih/2 + 4})`}
                style={{ letterSpacing: "0.25em" }}>张力 TENSION</text>

          {/* non-focused curves */}
          {!focused && visible.map(p => (
            <path key={p.id} d={smoothPath(pts(p))}
                  fill="none" stroke={genreColor(p.genre)} strokeOpacity="0.45" strokeWidth="1.5" />
          ))}

          {/* focused curve area + line */}
          {focused && (() => {
            const ps = pts(focused);
            const area = `${smoothPath(ps)} L ${ps[ps.length-1][0]} ${pad.t + ih} L ${ps[0][0]} ${pad.t + ih} Z`;
            return (
              <g>
                <defs>
                  <linearGradient id="arcGrad" x1="0" x2="0" y1="0" y2="1">
                    <stop offset="0%" stopColor={genreColor(focused.genre)} stopOpacity="0.45" />
                    <stop offset="100%" stopColor={genreColor(focused.genre)} stopOpacity="0.02" />
                  </linearGradient>
                </defs>
                <path d={area} fill="url(#arcGrad)" />
                <path d={smoothPath(ps)} fill="none" stroke={genreColor(focused.genre)} strokeWidth="2.4" />
                {ps.map(([x,y], i) => {
                  const peak = i === ps.findIndex((_,j) => focused.tension[j] === Math.max(...focused.tension));
                  return (
                    <g key={i}>
                      <line x1={x} y1={y} x2={x} y2={pad.t + ih} stroke="var(--ink-4)" strokeWidth="0.5" />
                      {/* presence dot for selected char */}
                      {selectedCharData && selectedCharData.playId === focused.id && selectedCharData.presence && selectedCharData.presence[i] === 1 && (
                        <circle cx={x} cy={pad.t + ih + 12} r="3.5" fill="var(--gold)" />
                      )}
                      <circle cx={x} cy={y} r={peak ? 5 : 3.5}
                              fill={peak ? "var(--vermillion)" : "var(--ink-2)"}
                              stroke={peak ? "var(--gold)" : genreColor(focused.genre)} strokeWidth="1.5" />
                      <text x={x} y={pad.t + ih + 24} fontSize="11" textAnchor="middle" fill="var(--paper)" fontFamily="var(--f-serif)" style={{ letterSpacing: "0.05em" }}>
                        {focused.acts[i]}
                      </text>
                      <text x={x} y={pad.t + ih + 36} fontSize="9" textAnchor="middle" className="mono label-dim">
                        第{["一","二","三","四","五","六","七","八","九"][i]}场
                      </text>
                      {peak && (
                        <text x={x} y={y - 12} fontSize="10" textAnchor="middle" fill="var(--vermillion-2)" fontFamily="var(--f-display)" style={{ letterSpacing: "0.1em" }}>
                          高潮
                        </text>
                      )}
                    </g>
                  );
                })}
              </g>
            );
          })()}

          {/* legend (bottom-left): which plays are overlaid when no focus */}
          {!focused && (
            <g transform={`translate(${pad.l}, ${H - 6})`}>
              <text fontSize="9" className="mono label-dim" style={{ letterSpacing:"0.2em" }}>
                ※ 选剧目以聚焦  ·  红线 历史 / 金线 家庭 / 翠线 公案
              </text>
            </g>
          )}
        </svg>
      </div>
    </div>
  );
}

window.NarrativeArc = NarrativeArc;
