/* ============================================================
   AFTERWAVE PLATFORM — VIZ  (window.VZ)
   Grayscale-dominant; sentiment color only. Area trend, radar,
   h-bars, scatter, progress ring, agent graph, neural panel.
   ============================================================ */
(function () {
  "use strict";
  const { useState, useMemo } = React;
  const U = window.AU;
  const h = React.createElement;
  const SENT = { pos: "#5d8a6b", neu: "#9a9081", neg: "#bd6149" };

  /* ---- multi-series area / line trend (narrative drift, weekly perf) ---- */
  function Trend({ series, height = 240, yMax = 1, fmtY, area, xLabels, legend }) {
    const [ref, { w }] = U.useSize();
    const W = w || 640, H = height, L = 40, R = 18, Tp = 16, B = 38;
    const n = series[0].data.length;
    const x = (i) => L + (i / (n - 1)) * (W - L - R);
    const y = (v) => Tp + (1 - v / yMax) * (H - Tp - B);
    const STROKE = { solid: "0", dash: "5 4", dot: "2 4" };
    return h("div", { ref, style: { width: "100%" } },
      h("svg", { width: W, height: H, style: { display: "block" }, role: "img", "aria-label": "trend" },
        [0, .25, .5, .75, 1].map((g, i) => h("g", { key: i },
          h("line", { x1: L, y1: y(g * yMax), x2: W - R, y2: y(g * yMax), stroke: "var(--line)", strokeWidth: 1 }),
          h("text", { x: L - 8, y: y(g * yMax) + 3, textAnchor: "end", className: "num", fontSize: 9, fill: "var(--ink-3)" }, fmtY ? fmtY(g * yMax) : Math.round(g * yMax * 100)))),
        (xLabels || []).map((lb, i) => h("text", { key: i, x: x(i * ((n - 1) / (xLabels.length - 1))), y: H - 14, textAnchor: "middle", className: "num", fontSize: 9, fill: "var(--ink-3)" }, lb)),
        series.map((s, si) => {
          const line = s.data.map((v, i) => (i ? "L" : "M") + x(i).toFixed(1) + " " + y(v).toFixed(1)).join(" ");
          const col = s.color || "var(--ink)";
          return h("g", { key: si },
            area && si === 0 ? h("path", { d: line + ` L ${x(n - 1)} ${y(0)} L ${x(0)} ${y(0)} Z`, fill: "var(--d0)", opacity: .8 }) : null,
            h("path", { d: line, fill: "none", stroke: col, strokeWidth: 1.9, strokeDasharray: STROKE[s.style || "solid"], strokeLinejoin: "round" }),
            s.dots ? s.data.map((v, i) => h("circle", { key: i, cx: x(i), cy: y(v), r: 2.4, fill: "var(--surface)", stroke: col, strokeWidth: 1.5 })) : null);
        })),
      legend ? h("div", { style: { display: "flex", gap: 16, flexWrap: "wrap", marginTop: 6, justifyContent: "center" } },
        series.map((s, i) => h("span", { key: i, style: { display: "inline-flex", alignItems: "center", gap: 7, fontSize: 11.5, color: "var(--ink-2)" } },
          h("svg", { width: 22, height: 8 }, h("line", { x1: 0, y1: 4, x2: 22, y2: 4, stroke: s.color || "var(--ink)", strokeWidth: 2, strokeDasharray: STROKE[s.style || "solid"] })), s.name))) : null);
  }

  /* ---- radar (content signal profile) ---- */
  function Radar({ axes, size = 230, max = 1 }) {
    const n = axes.length, cx = size / 2, cy = size / 2, Rr = size * 0.32;
    const ang = (i) => -Math.PI / 2 + (i / n) * Math.PI * 2;
    const pt = (i, v) => [cx + Math.cos(ang(i)) * Rr * (v / max), cy + Math.sin(ang(i)) * Rr * (v / max)];
    return h("svg", { width: size, height: size, role: "img", "aria-label": "signal profile" },
      [.33, .66, 1].map((g, gi) => h("polygon", { key: gi, points: axes.map((_, i) => pt(i, g * max).join(",")).join(" "), fill: "none", stroke: "var(--line)", strokeWidth: 1 })),
      axes.map((_, i) => h("line", { key: i, x1: cx, y1: cy, x2: pt(i, max)[0], y2: pt(i, max)[1], stroke: "var(--line)", strokeWidth: 1 })),
      h("polygon", { points: axes.map((a, i) => pt(i, a.value).join(",")).join(" "), fill: "var(--d2)", fillOpacity: .5, stroke: "var(--ink)", strokeWidth: 1.6 }),
      axes.map((a, i) => h("circle", { key: i, cx: pt(i, a.value)[0], cy: pt(i, a.value)[1], r: 2.3, fill: "var(--ink)" })),
      axes.map((a, i) => { const [px, py] = pt(i, max * 1.22); return h("text", { key: i, x: px, y: py + 3, textAnchor: px < cx - 4 ? "end" : px > cx + 4 ? "start" : "middle", fontSize: 9.5, fill: "var(--ink-2)" }, a.axis); }));
  }

  /* ---- horizontal bars (segment perf, resistance analysis, trait activation) ---- */
  function HBars({ rows, lblw = 128, fmt, tone, accent }) {
    const max = Math.max(...rows.map((r) => r.value), 1e-6);
    return h("div", { className: "hbars" }, rows.map((r) =>
      h("div", { key: r.label, className: "hbar", style: { "--lblw": lblw + "px" } },
        h("span", { className: "l" }, r.label),
        h("div", { className: "t" }, h("i", { style: { width: (r.value / max * 100) + "%", background: r.color || (tone ? SENT[tone] : "var(--d4)") } })),
        h("span", { className: "v" }, (fmt || ((x) => Math.round(x)))(r.value)))));
  }

  /* ---- progress ring (running) ---- */
  function Ring({ pct, size = 150, label, sub }) {
    const r = size / 2 - 9, c = 2 * Math.PI * r, off = c * (1 - pct);
    return h("div", { style: { position: "relative", width: size, height: size, flex: "none" } },
      h("svg", { width: size, height: size, style: { transform: "rotate(-90deg)" } },
        h("circle", { cx: size / 2, cy: size / 2, r, fill: "none", stroke: "var(--sunken)", strokeWidth: 7 }),
        h("circle", { cx: size / 2, cy: size / 2, r, fill: "none", stroke: "var(--ink)", strokeWidth: 7, strokeLinecap: "round", strokeDasharray: c, strokeDashoffset: off, style: { transition: "stroke-dashoffset .3s var(--ease)" } })),
      h("div", { style: { position: "absolute", inset: 0, display: "grid", placeItems: "center", textAlign: "center" } },
        h("div", null, h("div", { className: "num", style: { fontSize: 28, fontWeight: 500 } }, Math.round(pct * 100) + "%"),
          sub ? h("div", { className: "dim-2", style: { fontSize: 11 } }, sub) : null)));
  }

  /* ---- sentiment cluster scatter ---- */
  function Scatter({ points, height = 230 }) {
    const [ref, { w }] = U.useSize();
    const W = w || 420, H = height, L = 36, R = 16, Tp = 14, B = 32;
    const x = (v) => L + v * (W - L - R);
    const y = (v) => Tp + (1 - v) * (H - Tp - B);
    return h("div", { ref, style: { width: "100%" } },
      h("svg", { width: W, height: H, style: { display: "block" }, role: "img", "aria-label": "sentiment by segment" },
        [0, .5, 1].map((g, i) => h("line", { key: i, x1: L, y1: y(g), x2: W - R, y2: y(g), stroke: "var(--line)", strokeWidth: 1 })),
        h("text", { x: L - 8, y: y(.95), textAnchor: "end", className: "eyebrow", fontSize: 8, fill: "var(--ink-3)" }, "pos"),
        h("text", { x: L - 8, y: y(.05) + 6, textAnchor: "end", className: "eyebrow", fontSize: 8, fill: "var(--ink-3)" }, "neg"),
        h("text", { x: (L + W - R) / 2, y: H - 4, textAnchor: "middle", className: "eyebrow", fontSize: 8, fill: "var(--ink-3)" }, "engagement →"),
        points.map((p, i) => {
          const tone = p.y > .56 ? "pos" : p.y < .42 ? "neg" : "neu";
          return h("g", { key: i, onMouseMove: (e) => U.T(e, `<b>${p.seg}</b><br><span class='k'>sentiment</span> ${(p.y * 100).toFixed(0)}%`), onMouseLeave: U.hideTip },
            h("circle", { cx: x(p.x), cy: y(p.y), r: 5 + p.size * 9, fill: SENT[tone], fillOpacity: .22, stroke: SENT[tone], strokeWidth: 1.5 }));
        })));
  }

  /* ---- agent interaction graph ---- */
  function AgentGraph({ graph, height = 340 }) {
    const [ref, { w }] = U.useSize();
    const [sel, setSel] = useState(null);
    const W = w || 640, H = height;
    const pos = useMemo(() => {
      const m = {}; graph.nodes.forEach((nd) => m[nd.id] = { x: 60 + nd.x * (W - 120), y: 30 + nd.y * (H - 60) }); return m;
    }, [W, H, graph]);
    if (!w) return h("div", { ref, style: { width: "100%", height: H } });
    const neigh = new Set();
    if (sel) { neigh.add(sel); graph.edges.forEach((e) => { if (e.a === sel) neigh.add(e.b); if (e.b === sel) neigh.add(e.a); }); }
    return h("div", { ref, style: { width: "100%" } },
      h("svg", { width: W, height: H, style: { display: "block" }, role: "img", "aria-label": "agent interaction graph" },
        graph.edges.map((e, i) => { const a = pos[e.a], b = pos[e.b]; const faded = sel && !(neigh.has(e.a) && neigh.has(e.b));
          return h("line", { key: i, x1: a.x, y1: a.y, x2: b.x, y2: b.y, stroke: "var(--line-3)", strokeWidth: .5 + e.w * 1.5, opacity: faded ? .1 : .5 }); }),
        graph.nodes.map((nd) => { const p = pos[nd.id]; const r = 6 + nd.influence * 12; const faded = sel && !neigh.has(nd.id);
          return h("g", { key: nd.id, transform: `translate(${p.x},${p.y})`, style: { cursor: "pointer", opacity: faded ? .25 : 1, transition: "opacity .2s" },
            onClick: () => setSel(sel === nd.id ? null : nd.id),
            onMouseMove: (e) => U.T(e, `<b>${nd.role}</b><br><span class='k'>sentiment</span> ${nd.sent}<br><span class='k'>influence</span> ${(nd.influence * 100).toFixed(0)}%`), onMouseLeave: U.hideTip },
            h("circle", { r, fill: SENT[nd.sent], fillOpacity: .82, stroke: "var(--surface)", strokeWidth: 2 }),
            sel === nd.id ? h("circle", { r: r + 4, fill: "none", stroke: "var(--ink)", strokeWidth: 1.5 }) : null); })),
      h("div", { style: { display: "flex", gap: 16, marginTop: 8, flexWrap: "wrap" } },
        [["pos", "positive"], ["neu", "neutral"], ["neg", "negative"]].map(([t, l]) =>
          h("span", { key: t, style: { display: "inline-flex", alignItems: "center", gap: 6, fontSize: 11, color: "var(--ink-2)" } },
            h("span", { style: { width: 9, height: 9, borderRadius: "50%", background: SENT[t] } }), l)),
        h("span", { className: "dim-2", style: { fontSize: 11, marginLeft: "auto" } }, "node size = influence · click to isolate")));
  }

  window.VZ = { Trend, Radar, HBars, Ring, Scatter, AgentGraph, SENT };
})();
