// Career visualizations — waveform grammar applied to a career timeline.
// CareerWave: one long animated wave, envelope = career scope, peaks at milestones.
// RidgeTerrain: stacked ridgelines, one per role — position = tenure, height = scope.

const YR0 = 2005.7, YR1 = 2027.0;

function xOf(year, W) {
  return ((year - YR0) / (YR1 - YR0)) * W;
}

// raised-cosine envelope for one role at x
function bumpAt(x, xs, xe, edgeMax = 60) {
  const edge = Math.min(edgeMax, (xe - xs) * 0.4);
  if (x <= xs - edge || x >= xe + edge) return 0;
  if (x < xs + edge) return 0.5 - 0.5 * Math.cos((Math.PI * (x - (xs - edge))) / (2 * edge));
  if (x > xe - edge) return 0.5 - 0.5 * Math.cos((Math.PI * ((xe + edge) - x)) / (2 * edge));
  return 1;
}

// CAREER WAVE — bars with a career-shaped envelope, gently breathing
function CareerWave({ roles, milestones, height = 240, showMilestones = true }) {
  const { useEffect, useRef, useState } = React;
  const [t, setT] = useState(0);
  const ref = useRef(null);
  const [w, setW] = useState(1100);
  useEffect(() => {
    const ro = new ResizeObserver((e) => setW(e[0].contentRect.width));
    if (ref.current) ro.observe(ref.current);
    return () => ro.disconnect();
  }, []);
  useEffect(() => {
    let raf;
    const tick = () => { setT((v) => v + 0.016); raf = requestAnimationFrame(tick); };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, []);

  const envAt = (x) => {
    let e = 0;
    for (const r of roles) e += r.scope * bumpAt(x, xOf(r.start, w), xOf(r.end, w));
    return Math.min(1.12, e);
  };

  const n = 200;
  const gap = 2;
  const barW = Math.max(1, (w - gap * (n - 1)) / n);
  const bars = [];
  for (let i = 0; i < n; i++) {
    const x = i * (barW + gap) + barW / 2;
    const env = envAt(x);
    const wob = 0.62
      + 0.22 * Math.sin(i * 0.55 + t * 1.1)
      + 0.11 * Math.sin(i * 1.7 - t * 1.9)
      + 0.05 * Math.sin(i * 3.1 + t * 0.7);
    const h = Math.max(1.5, env * height * 0.88 * wob);
    bars.push({ x: i * (barW + gap), h });
  }

  const years = [];
  for (let y = 2006; y <= 2026; y += 2) years.push(y);

  return (
    <div className="career-wrap" ref={ref}>
      <svg viewBox={`0 0 ${w} ${height}`} width="100%" height={height} preserveAspectRatio="none" style={{ display: "block" }}>
        {years.map((y) => (
          <line key={y} x1={xOf(y, w)} y1={0} x2={xOf(y, w)} y2={height} stroke="var(--line)" strokeDasharray="2 5" strokeWidth="1" />
        ))}
        {bars.map((b, i) => (
          <rect key={i} x={b.x} y={height - b.h} width={barW} height={b.h} fill="currentColor" />
        ))}
        <line x1="0" y1={height - 0.5} x2={w} y2={height - 0.5} stroke="var(--line)" strokeWidth="1" />
      </svg>
      {showMilestones && milestones.map((m) => {
        const left = (xOf(m.y, w) / w) * 100;
        const env = envAt(xOf(m.y, w));
        return (
          <div key={m.label} className="ms" style={{ left: `${left}%`, bottom: `${Math.min(96, env * 88 + 6)}%` }}>
            <span className="ms-dot"></span>
            <span className="ms-chip mono">
              <span className="ms-yr">{Math.floor(m.y)}</span> {m.label}
              <span className="ms-sub">{m.sub}</span>
            </span>
          </div>
        );
      })}
      <div className="year-ruler mono">
        {years.map((y) => (
          <span key={y} style={{ left: `${(xOf(y, w) / w) * 100}%` }}>{String(y).slice(2)}</span>
        ))}
      </div>
    </div>
  );
}

// RIDGE TERRAIN — one ridge per role, drawn back-to-front with bg fill occlusion
function RidgeTerrain({ roles, activeId, onActive }) {
  const { useEffect, useRef, useState } = React;
  const ref = useRef(null);
  const [w, setW] = useState(1100);
  useEffect(() => {
    const ro = new ResizeObserver((e) => setW(e[0].contentRect.width));
    if (ref.current) ro.observe(ref.current);
    return () => ro.disconnect();
  }, []);

  const rowGap = 56;
  const rise = 96;
  const topPad = rise + 18;
  const H = topPad + (roles.length - 1) * rowGap + 46;

  const ridge = (r, i) => {
    const base = topPad + i * rowGap;
    const xs = xOf(r.start, w), xe = xOf(r.end, w);
    const pts = [];
    for (let x = 0; x <= w; x += 6) {
      const e = bumpAt(x, xs, xe);
      const tex = 0.82 + 0.13 * Math.sin(x * 0.045 + i * 2.3) + 0.05 * Math.sin(x * 0.013 + i * 1.1);
      pts.push([x, base - r.scope * rise * e * tex]);
    }
    return { base, xs, xe, pts };
  };

  const pathOf = (pts) => pts.map((p, j) => (j === 0 ? "M" : "L") + p[0].toFixed(1) + " " + p[1].toFixed(1)).join(" ");
  const years = [];
  for (let y = 2006; y <= 2026; y += 4) years.push(y);

  return (
    <div ref={ref} className="terrain-wrap">
      <svg viewBox={`0 0 ${w} ${H}`} width="100%" height="auto" style={{ display: "block" }}>
        {years.map((y) => (
          <line key={y} x1={xOf(y, w)} y1={0} x2={xOf(y, w)} y2={H - 26} stroke="var(--line)" strokeDasharray="2 6" strokeWidth="1" />
        ))}
        {roles.map((r, i) => {
          const { base, xs, pts } = ridge(r, i);
          const d = pathOf(pts);
          const closed = d + ` L ${w} ${base + rowGap * 0.9} L 0 ${base + rowGap * 0.9} Z`;
          const on = activeId === r.id;
          const dim = activeId && !on;
          // echo slices under the crest
          const echo = (f) => pathOf(pts.map(([x, y]) => [x, base - (base - y) * f]));
          return (
            <g key={r.id}
               style={{ cursor: "pointer", transition: "opacity 0.25s" }}
               opacity={dim ? 0.35 : 1}
               onMouseEnter={() => onActive && onActive(r.id)}
               onClick={() => onActive && onActive(r.id)}>
              <path d={closed} fill="var(--bg)" stroke="none" pointerEvents="all" />
              <path d={echo(0.62)} fill="none" stroke={on ? "var(--accent)" : "var(--fg-faint)"} strokeWidth="0.8" opacity="0.5" />
              <path d={echo(0.3)} fill="none" stroke={on ? "var(--accent)" : "var(--fg-faint)"} strokeWidth="0.8" opacity="0.3" />
              <path d={d} fill="none" stroke={on ? "var(--accent)" : "var(--fg-dim)"} strokeWidth={on ? 1.6 : 1.1} />
              <text x={Math.min(Math.max(xs, 8), w - 310)} y={base + 16} className={"svg-lbl" + (on ? " on" : "")}>
                {r.company.toUpperCase()}
                <tspan className="svg-lbl dim">{"\u00A0\u00A0\u00B7\u00A0\u00A0" + r.dates}</tspan>
              </text>
            </g>
          );
        })}
        {years.map((y) => (
          <text key={"t" + y} x={xOf(y, w)} y={H - 8} textAnchor="middle" className="svg-tick">{y}</text>
        ))}
      </svg>
    </div>
  );
}

window.CareerWave = CareerWave;
window.RidgeTerrain = RidgeTerrain;
