/* global React, TONES */

// ============================================================
// Career trajectory line chart.
// Purely presentational + controlled. The parent owns `active`.
//
//   chart = {
//     levels: ["Associate PM", ... ]   // low → high (y axis)
//     currentLevel: 2,                  // index into levels (the "you" band)
//     tStart: -6,                       // earliest time on x axis (years; now = 0)
//     past:  [{ t, lvl, label, year, now?, co? }]   // history, ends at now (t=0)
//   }
//   paths = [{ key, name, tone, nodes:[{ t, lvl, label, sub?, milestone?, aspirational?, dy? }] }]
//   horizon = furthest future year shown   active = key|null   detail = 1|2|3
// ============================================================

// Warm-palette literals (CSS vars don't resolve inside SVG attributes).
const TC = {
  ink: "#1F1B16", ink700: "#3A332B", ink500: "#5C544A", ink300: "#B8AE9C",
  line: "#E8E2D5", lineSoft: "#F1ECE1", cardinal: "#8C1515", paper: "#FFFFFF",
};

const TrajectoryChart = ({ chart, paths, horizon = 5, detail = 2, active = null, onHover = () => {}, onSelect = () => {} }) => {
  const W = 1040, H = 384;
  const PAD = { l: 150, r: 34, t: 30, b: 42 };
  const plotW = W - PAD.l - PAD.r;
  const plotH = H - PAD.t - PAD.b;
  const tMin = chart.tStart, tMax = horizon;
  const maxLvl = chart.levels.length - 1;
  const xs = (t) => PAD.l + ((t - tMin) / (tMax - tMin)) * plotW;
  const ys = (lvl) => PAD.t + (1 - lvl / maxLvl) * plotH;
  const baseYear = chart.past[chart.past.length - 1].year;
  const curLvl = chart.currentLevel;
  const nowX = xs(0);

  // X-axis ticks: every 2 years, plus "Now".
  const ticks = [];
  for (let t = Math.ceil(tMin / 2) * 2; t <= tMax + 0.001; t += 2) ticks.push(t);
  if (!ticks.includes(0)) ticks.push(0);

  const pastPts = chart.past.map((p) => `${xs(p.t)},${ys(p.lvl)}`).join(" ");

  return (
    <div style={{ width: "100%", overflow: "hidden" }}>
      <svg viewBox={`0 0 ${W} ${H}`} width="100%" role="img"
        aria-label="Career trajectory chart"
        style={{ display: "block", fontFamily: "Inter, sans-serif" }}>

        {/* Past region tint + "history / ahead" captions */}
        <rect x={PAD.l} y={PAD.t} width={Math.max(0, nowX - PAD.l)} height={plotH} fill="rgba(31,27,22,0.022)"/>
        <text x={(PAD.l + nowX) / 2} y={PAD.t - 13} textAnchor="middle" fontSize="10" fontWeight="600"
          letterSpacing="0.09em" fill={TC.ink300}>PATH SO FAR</text>
        <text x={(nowX + W - PAD.r) / 2} y={PAD.t - 13} textAnchor="middle" fontSize="10" fontWeight="600"
          letterSpacing="0.09em" fill={TC.ink300}>POSSIBLE MOVES</text>

        {/* Y gridlines + level labels */}
        {chart.levels.map((lab, i) => {
          const y = ys(i);
          const isCur = i === curLvl;
          return (
            <g key={`y${i}`}>
              <line x1={PAD.l} y1={y} x2={W - PAD.r} y2={y}
                stroke={isCur ? "rgba(140,21,21,0.16)" : TC.lineSoft} strokeWidth="1"/>
              <text x={PAD.l - 14} y={y + 4} textAnchor="end" fontSize="11.5"
                fontWeight={isCur ? 700 : 500} fill={isCur ? TC.cardinal : TC.ink500}>{lab}</text>
            </g>
          );
        })}

        {/* X ticks */}
        {ticks.map((t, i) => (
          <text key={`x${i}`} x={xs(t)} y={H - 14} textAnchor="middle" fontSize="10.5"
            fontWeight={t === 0 ? 700 : 500} fill={t === 0 ? TC.ink700 : TC.ink300}>
            {t === 0 ? "Now" : baseYear + t}
          </text>
        ))}

        {/* "Now" divider */}
        <line x1={nowX} y1={PAD.t - 2} x2={nowX} y2={H - PAD.b} stroke="rgba(31,27,22,0.20)"
          strokeWidth="1" strokeDasharray="3 4"/>

        {/* ---- Future path lines ---- */}
        {paths.map((p) => {
          const tone = TONES[p.tone];
          const isOn = active === p.key;
          const dim = active && !isOn;
          const pts = [{ t: 0, lvl: curLvl }, ...p.nodes.filter((n) => n.t <= tMax)];
          const segs = [];
          for (let i = 1; i < pts.length; i++) {
            const a = pts[i - 1], b = pts[i];
            segs.push(
              <line key={i} x1={xs(a.t)} y1={ys(a.lvl)} x2={xs(b.t)} y2={ys(b.lvl)}
                stroke={tone.color} strokeWidth={isOn ? 3.6 : 2.3} strokeLinecap="round"
                strokeOpacity={dim ? 0.14 : 0.92}
                strokeDasharray={b.aspirational ? "6 5" : "none"}/>
            );
          }
          return <g key={p.key}>{segs}</g>;
        })}

        {/* ---- Path nodes + labels (over the lines) ---- */}
        {paths.map((p) => {
          const tone = TONES[p.tone];
          const isOn = active === p.key;
          const dim = active && !isOn;
          return p.nodes.filter((n) => n.t <= tMax).map((n, i) => {
            const x = xs(n.t), y = ys(n.lvl);
            const showLabel = isOn || detail >= 3;
            const anchorEnd = x > W - PAD.r - 150;
            const lx = anchorEnd ? x - 11 : x + 11;
            return (
              <g key={`${p.key}${i}`} opacity={dim ? 0.18 : 1}>
                <circle cx={x} cy={y} r={n.milestone ? 5.6 : 4.4} fill={TC.paper}
                  stroke={tone.color} strokeWidth="2.6"/>
                {n.milestone && <circle cx={x} cy={y} r="2.1" fill={tone.color}/>}
                {showLabel && (
                  <text x={lx} y={y + (n.dy || -9)} textAnchor={anchorEnd ? "end" : "start"} fontSize="12" fontWeight="700" fill={tone.text}>
                    {n.label}
                    {n.sub && <tspan x={lx} dy="14" fontSize="10.5" fontWeight="500" fill={TC.ink500}>{n.sub}</tspan>}
                  </text>
                )}
              </g>
            );
          });
        })}

        {/* ---- Past line + nodes ---- */}
        <polyline points={pastPts} fill="none" stroke={TC.ink700} strokeWidth="2.8"
          strokeLinecap="round" strokeLinejoin="round"/>
        {chart.past.map((p, i) => {
          const x = xs(p.t), y = ys(p.lvl);
          if (p.now) {
            return (
              <g key={`p${i}`}>
                <circle cx={x} cy={y} r="13" fill="rgba(140,21,21,0.12)"/>
                <circle cx={x} cy={y} r="8.5" fill={TC.cardinal}/>
                <circle cx={x} cy={y} r="3.2" fill={TC.paper}/>
                <text x={x} y={y + 28} textAnchor="middle" fontSize="12.5" fontWeight="700" fill={TC.ink}>You are here</text>
                <text x={x} y={y + 43} textAnchor="middle" fontSize="11" fill={TC.ink500}>
                  {p.label}{p.co ? ` · ${p.co}` : ""}
                </text>
              </g>
            );
          }
          return (
            <g key={`p${i}`}>
              <circle cx={x} cy={y} r="4.2" fill={TC.ink700}/>
              {detail >= 2 && (
                <text x={x} y={y - 13} textAnchor="middle" fontSize="11" fontWeight="600" fill={TC.ink700}>{p.label}</text>
              )}
            </g>
          );
        })}

        {/* ---- Wide transparent hit-lines (topmost) so hovering the line works ---- */}
        {paths.map((p) => {
          const pts = [{ t: 0, lvl: curLvl }, ...p.nodes.filter((n) => n.t <= tMax)]
            .map((n) => `${xs(n.t)},${ys(n.lvl)}`).join(" ");
          return (
            <polyline key={`hit${p.key}`} points={pts} fill="none" stroke="transparent"
              strokeWidth="22" strokeLinecap="round" strokeLinejoin="round"
              style={{ cursor: "pointer", pointerEvents: "stroke" }}
              onMouseEnter={() => onHover(p.key)} onMouseLeave={() => onHover(null)}
              onClick={() => onSelect(p.key)}/>
          );
        })}
      </svg>
    </div>
  );
};

window.TrajectoryChart = TrajectoryChart;
