// StrikeSimple — Split diagrams: the wheel's two entry splits, cut out of the wheel
// (assets/diagrams/wheel-state-graph.svg) at its own coordinates, for the Primitives section's
// Wing and Anchor. CallSplit: T splits into T − CALL S0 (the Upside Anchor) and +CALL S0 (the
// Upside Wing). PutSplit: Cash splits into Cash − PUT S0 (the Downside Anchor) and +PUT S0 (the
// Downside Wing). The edges that run on into the rest of the wheel are kept as short stubs that
// fade out (a mask over the edges and beams), and the comet beams run as in the wheel. Each block
// is hover-shiny in its product colour and swaps its label to the product token, as in the wheel;
// `highlight` lists the blocks (by id, see SPLIT_NODES) to light up in the beam's lavender. Dark
// only, like the wheel. Exposes window.CallSplit and window.PutSplit.

// Block (keyed by its rect's x, as in WheelGraph) → { palette p, token t shown on hover, id }.
const SPLIT_NODES = {
  "289": { p: "sun",    t: "call_n", id: "call-s0" },     // +CALL S0
  "414": { p: "flame",  t: "call_p", id: "t-call-s0" },   // T − CALL S0
  "793": { p: "cobalt", t: "put_p",  id: "cash-put-s0" }, // Cash − PUT S0
  "888": { p: "azure",  t: "put_n",  id: "put-s0" },      // +PUT S0
};

// Each split: its window onto the wheel (`box`, the viewBox — both the same size, so switching
// between them doesn't move anything), its `edges` (the wheel's paths, whole, so the beams keep the
// wheel's pace), the mask that shows them — `keep` (x, y, w, h) shown in full, `stubs` (x, y, w, h,
// direction) fading out in that direction — and its arrow and blocks, as the wheel draws them.
const SPLITS = {
  call: {
    label: "T splits into T − CALL S0 and +CALL S0",
    box: [121, 318, 556, 312],
    edges: [
      "M255,540 L414,540",          // T → T − CALL S0
      "M172,520 L172,403 L289,403", // T → +CALL S0
      "M436,678 L172,678 L172,560", // stubs: into T, from the wheel's T
      "M380,374 L380,299",          //   +CALL S0 → CALL S0 − CALL S1
      "M467,403 L551,403",          //   +CALL S0 → +CALL S1
      "M620,540 L816,540",          //   T − CALL S0 → Cash
      "M520,573 L520,635",          //   T − CALL S0 → T
    ],
    keep: [[248, 528, 174, 24], [160, 391, 136, 133]],
    stubs: [[158, 560, 28, 48, "down"], [366, 326, 28, 48, "up"], [471, 389, 48, 28, "right"], [620, 526, 48, 28, "right"], [506, 574, 28, 48, "down"]],
    body: `
  <polygon points="132,520 212,520 212,500 256,540 212,580 212,560 132,560" fill="#121215" stroke="#3C3C45" stroke-width="3" stroke-linejoin="round"></polygon>
  <text x="170" y="548" text-anchor="middle" font-size="22" letter-spacing=".01em" fill="#F2F2F3">T</text>
  <g fill="#121215" stroke="#3C3C45" stroke-width="3">
    <rect x="289" y="374" width="182" height="58" rx="4"></rect>
    <rect x="414" y="508" width="206" height="66" rx="4"></rect>
  </g>
  <g font-size="21" letter-spacing=".01em" fill="#F2F2F3" text-anchor="middle">
    <text x="380" y="409">+CALL<tspan font-size="0.66em" baseline-shift="sub">S0</tspan></text>
    <text x="520" y="546">T − CALL<tspan font-size="0.66em" baseline-shift="sub">S0</tspan></text>
  </g>`,
  },
  put: {
    label: "Cash splits into Cash − PUT S0 and +PUT S0",
    box: [732, 589, 556, 312],
    edges: [
      "M1150,678 L1011,678",           // Cash → Cash − PUT S0
      "M1228,700 L1228,815 L1056,815", // Cash → +PUT S0
      "M978,540 L1228,540 L1228,656",  // stubs: into Cash, from the wheel's Cash
      "M900,645 L900,581",             //   Cash − PUT S0 → Cash
      "M793,678 L606,678",             //   Cash − PUT S0 → T
      "M888,815 L804,815",             //   +PUT S0 → +PUT S1
      "M970,844 L970,919",             //   +PUT S0 → PUT S0 − PUT S1
    ],
    keep: [[1004, 666, 153, 24], [1049, 696, 191, 131]],
    stubs: [[1214, 608, 28, 48, "up"], [886, 597, 28, 48, "up"], [745, 664, 48, 28, "left"], [840, 801, 48, 28, "left"], [956, 844, 28, 48, "down"]],
    body: `
  <polygon points="1274,656 1182,656 1182,636 1136,678 1182,720 1182,700 1274,700" fill="#121215" stroke="#3C3C45" stroke-width="3" stroke-linejoin="round"></polygon>
  <text x="1230" y="686" text-anchor="middle" font-size="22" letter-spacing=".01em" fill="#F2F2F3">Cash</text>
  <g fill="#121215" stroke="#3C3C45" stroke-width="3">
    <rect x="793" y="645" width="214" height="66" rx="4"></rect>
    <rect x="888" y="786" width="164" height="58" rx="4"></rect>
  </g>
  <g font-size="21" letter-spacing=".01em" fill="#F2F2F3" text-anchor="middle">
    <text x="900" y="684">Cash − PUT<tspan font-size="0.66em" baseline-shift="sub">S0</tspan></text>
    <text x="970" y="821">+PUT<tspan font-size="0.66em" baseline-shift="sub">S0</tspan></text>
  </g>`,
  },
};

// A stub's gradient (x1 y1 x2 y2, in its rect): opaque where it leaves its block, clear at the end.
const SPLIT_FADES = { up: "0 1 0 0", down: "0 0 0 1", left: "1 0 0 0", right: "0 0 1 0" };
// The wheel's comet beam: 6 layered dashes sharing one moving head (see the wheel's SVG).
const SPLIT_BEAMS = [28, 21, 15, 10, 6, 3];

// The SVG for split `s`, its ids prefixed with `uid` (two can be mounted at once while one fades out).
const splitSvg = (s, uid) => {
  const [bx, by, bw, bh] = s.box;
  const rect = ([x, y, w, h], fill) => `<rect x="${x}" y="${y}" width="${w}" height="${h}" fill="${fill}"></rect>`;
  const paths = (extra) => s.edges.map((d) => `<path${extra} d="${d}"></path>`).join("");
  return `
<svg viewBox="${s.box.join(" ")}" role="img" aria-label="${s.label}">
  <defs>
    <filter id="${uid}-glow" x="-40%" y="-40%" width="180%" height="180%">
      <feGaussianBlur stdDeviation="2.2" result="b"></feGaussianBlur>
      <feMerge><feMergeNode in="b"></feMergeNode><feMergeNode in="SourceGraphic"></feMergeNode></feMerge>
    </filter>
    ${Object.entries(SPLIT_FADES).map(([dir, v]) => {
      const [x1, y1, x2, y2] = v.split(" ");
      return `<linearGradient id="${uid}-${dir}" x1="${x1}" y1="${y1}" x2="${x2}" y2="${y2}"><stop offset="0" stop-color="#fff"></stop><stop offset="1" stop-color="#000"></stop></linearGradient>`;
    }).join("")}
    <mask id="${uid}-mask" maskUnits="userSpaceOnUse" x="${bx}" y="${by}" width="${bw}" height="${bh}">
      ${s.keep.map((r) => rect(r, "#fff")).join("")}
      ${s.stubs.map((r) => rect(r, `url(#${uid}-${r[4]})`)).join("")}
    </mask>
    <g id="${uid}-beamPaths" fill="none">${paths(' pathLength="100"')}</g>
  </defs>
  <g mask="url(#${uid}-mask)">
    <g fill="none" stroke="#313139" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">${paths("")}</g>
    <g class="beams" fill="none" stroke="#A6A6FF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" filter="url(#${uid}-glow)">
      ${SPLIT_BEAMS.map((n) => `<g stroke-opacity="0.4" stroke-dasharray="${n} ${100 - n}"><animate attributeName="stroke-dashoffset" values="${n};${n - 100}" dur="2.6s" repeatCount="indefinite"></animate><use href="#${uid}-beamPaths"></use></g>`).join("")}
    </g>
  </g>${s.body}
</svg>`;
};

let splitSeq = 0;

function SplitGraph({ side, style, highlight }) {
  const ref = React.useRef(null);
  const [svg] = React.useState(() => splitSvg(SPLITS[side], `sg${++splitSeq}`));
  const hl = (highlight || []).join(" ");

  // Tag each block with its palette class (CSS :hover shine) and, on hover, crossfade its label
  // to the product token — reverting on mouse-leave. Mirrors WheelGraph.
  React.useLayoutEffect(() => {
    const root = ref.current && ref.current.querySelector("svg");
    if (!root) return;
    const texts = Array.from(root.querySelectorAll("text"));
    const labelInside = (r) => {
      const x = +r.getAttribute("x"), y = +r.getAttribute("y");
      const w = +r.getAttribute("width"), h = +r.getAttribute("height");
      return texts.find((t) => {
        const tx = +t.getAttribute("x"), ty = +t.getAttribute("y");
        return tx >= x && tx <= x + w && ty >= y && ty <= y + h;
      });
    };
    const cleanups = [];
    root.querySelectorAll("rect:not(mask rect)").forEach((r) => {
      const node = SPLIT_NODES[r.getAttribute("x")];
      if (!node) return;
      r.classList.add("sg-node", "sg-" + node.p);
      r.dataset.node = node.id;
      const label = labelInside(r);
      if (!label) return;
      const original = label.innerHTML;
      label.style.transition = "opacity .14s ease";
      let timer;
      const swap = (apply) => {
        clearTimeout(timer);
        label.style.opacity = "0";
        timer = setTimeout(() => { apply(); label.style.opacity = "1"; }, 140);
      };
      const enter = () => swap(() => { label.textContent = node.t.toUpperCase(); });
      const leave = () => swap(() => { label.innerHTML = original; });
      r.addEventListener("mouseenter", enter);
      r.addEventListener("mouseleave", leave);
      cleanups.push(() => { clearTimeout(timer); r.removeEventListener("mouseenter", enter); r.removeEventListener("mouseleave", leave); });
    });
    // T / Cash: the entry arrow shines neutral; its label stays.
    root.querySelectorAll("polygon").forEach((el) => el.classList.add("sg-node", "sg-neutral"));
    return () => cleanups.forEach((fn) => fn());
  }, []);

  // Light up the `highlight`ed blocks.
  React.useLayoutEffect(() => {
    const root = ref.current && ref.current.querySelector("svg");
    if (!root) return;
    const ids = hl.split(" ");
    root.querySelectorAll("rect[data-node]").forEach((r) => r.classList.toggle("is-hl", ids.includes(r.dataset.node)));
  }, [hl]);

  return (
    <div ref={ref} className="split-graph" style={{ width: "100%", margin: "0 auto", padding: 14, boxSizing: "border-box", ...style }}>
      <style>{`
        .split-graph { max-width: 640px; } /* in a stylesheet, not inline, so a page can size it */
        /* overflow visible: the T / Cash arrow sits near the edge, and its hover glow would be cut off
           (the edges and beams stay clipped to the box by their mask). */
        .split-graph svg { width: 100%; height: auto; display: block; overflow: visible; }
        /* Labels sit on top of the blocks — let pointer events fall through so hovering a label
           still triggers its block's shine. */
        .split-graph svg text { pointer-events: none; font-family: var(--lp-font); }
        .split-graph .sg-node { fill: #121215; stroke: #3C3C45; cursor: pointer; transition: stroke .35s ease, fill .35s ease, filter .35s ease; }
        /* Highlighted blocks — lit in the beam's lavender (hovering still shines them in their own colour). */
        .split-graph .sg-node.is-hl { stroke: var(--blue-300); fill: color-mix(in srgb, var(--blue-400) 26%, #121215); filter: drop-shadow(0 0 10px rgb(87 87 255 / 0.5)); }
        /* Per-block hover shine — each block lights up in its product-palette colour (as in the wheel). */
        .split-graph .sg-sun:hover     { stroke: var(--sun-400);     fill: var(--sun-900);    filter: drop-shadow(0 0 13px var(--sun-500)); }
        .split-graph .sg-flame:hover   { stroke: var(--flame-400);   fill: var(--flame-900);  filter: drop-shadow(0 0 13px var(--flame-500)); }
        .split-graph .sg-cobalt:hover  { stroke: var(--cobalt-400);  fill: var(--cobalt-900); filter: drop-shadow(0 0 13px var(--cobalt-500)); }
        .split-graph .sg-azure:hover   { stroke: var(--azure-400);   fill: var(--azure-900);  filter: drop-shadow(0 0 13px var(--azure-500)); }
        .split-graph .sg-neutral:hover { stroke: var(--surface-card); fill: var(--gray-800);  filter: drop-shadow(0 0 13px var(--surface-card)); }
      `}</style>
      <div dangerouslySetInnerHTML={{ __html: svg }} />
    </div>
  );
}

const CallSplit = (props) => <SplitGraph side="call" {...props} />;
const PutSplit = (props) => <SplitGraph side="put" {...props} />;

window.CallSplit = CallSplit;
window.PutSplit = PutSplit;
