// Mission 001 — staged network graph. Layer rings, not degree rings: this system claims no view of anyone's network.
const NetGraph = ({ stage, density = "standard", mini = false }) => {
  const { NODES, EDGES, AMBIENT } = MD;
  const N = Object.fromEntries(NODES.map(n => [n.id, n]));
  const complete = MD.STAGES[stage].complete;

  const visN = NODES.filter(n => stage >= n.s && (n.until == null || stage < n.until));
  const visE = EDGES.filter(([a, b, s, o]) => stage >= s && (o.until == null || stage < o.until)
    && visN.some(n => n.id === a) && visN.some(n => n.id === b));

  const isHot = (o) => o.hot && stage >= o.hot[0] && stage < o.hot[1];
  const isDown = (o) => o.downAt != null && stage >= o.downAt;
  const tierMax = density === "sparse" ? 0 : density === "dense" ? 2 : 1;

  const nodeState = (n) => {
    if (n.deadAt != null && stage >= n.deadAt) return "dead";
    if (n.clearedAt != null && stage >= n.clearedAt) return "cleared";
    return "norm";
  };

  const shape = (n) => {
    const st = nodeState(n);
    if (n.type === "dest") {
      const lead = MD.STAGES[stage].dest === n.dest;
      const won = complete && lead;
      const dim = (complete && !lead) || st === "dead";
      return (
        <g opacity={dim ? 0.3 : 1}>
          {won && <circle r={n.r + 14} fill="none" stroke="#3DDB8E" strokeWidth="1.5" opacity="0.6" className="ng-ring" />}
          {lead && !won && <circle r={n.r + 11} fill="none" stroke="#5B9DF5" strokeWidth="1" opacity="0.4" className="ng-ring" />}
          <rect x={-n.r} y={-n.r} width={n.r * 2} height={n.r * 2} transform="rotate(45)"
            fill="#0A1018" stroke={won ? "#3DDB8E" : "#5B9DF5"} strokeWidth="1.5" />
          <rect x={-n.r + 4} y={-n.r + 4} width={n.r * 2 - 8} height={n.r * 2 - 8} transform="rotate(45)"
            fill={won ? "#3DDB8E" : "#3D7EDB"} opacity="0.55" className={won ? "" : "ng-destpulse"} />
        </g>);
    }
    if (n.type === "you") return (
      <g>
        <circle r={n.r + 9} fill="none" stroke={complete ? "#3DDB8E" : "#5B9DF5"} strokeWidth="1" opacity="0.35" className="ng-ring" />
        <circle r={n.r} fill={complete ? "#3DDB8E" : "#5B9DF5"} />
        <circle r={4} fill="#04070D" />
      </g>);
    if (n.type === "frontier") return <circle r={n.r} fill="#2A4A78" className="ng-frontier" />;
    if (n.type === "org") return <rect x={-6} y={-6} width="12" height="12" fill="#10203A" stroke="#3D7EDB" strokeWidth="1.2" />;
    if (n.type === "event") return <rect x={-6} y={-6} width="12" height="12" transform="rotate(45)" fill="#10203A" stroke="#3D7EDB" strokeWidth="1.2" />;
    if (st === "dead") return (
      <g opacity="0.55">
        <circle r={n.r} fill="#0A1018" stroke="#7A3B36" strokeWidth="1.2" />
        <path d={`M${-4} ${-4} L4 4 M4 ${-4} L${-4} 4`} stroke="#C2564E" strokeWidth="1.4" />
      </g>);
    if (st === "cleared") return (
      <g>
        <circle r={n.r} fill="#123325" stroke="#3DDB8E" strokeWidth="1.4" />
        <path d="M-3.5 0.5 L-1 3 L4 -2.5" stroke="#3DDB8E" strokeWidth="1.6" fill="none" strokeLinecap="round" />
      </g>);
    return <circle r={n.r} fill="#10203A" stroke="#3D7EDB" strokeWidth="1.2" />;
  };

  return (
    <svg className={"ng-svg" + (mini ? " mini" : "")} viewBox="0 0 1040 580" fill="none"
      role="img" aria-label="Network exploration graph">
      <defs>
        <radialGradient id="ngglow" cx="50%" cy="45%" r="62%">
          <stop offset="0%" stopColor="#0E1B30" /><stop offset="100%" stopColor="#04070D" />
        </radialGradient>
      </defs>
      <rect width="1040" height="580" fill="url(#ngglow)" />

      {/* layer rings centred on the subject — mapped (public research), contacted, committed (ledger-grounded only) */}
      {!mini && [170, 365, 560].map((r, i) => (
        <g key={"dr" + i} opacity={stage >= i ? 0.8 : 0.25}>
          <circle cx="78" cy="295" r={r} fill="none" stroke="#131F30" strokeWidth="1" strokeDasharray="3 7" />
          <text x={78 + r - 14} y="286" fontFamily="'IBM Plex Mono', monospace" fontSize="10"
            fill={stage >= i ? "#2A4A78" : "#16263D"} letterSpacing="0.1em">{["MAPPED","CONTACTED","COMMITTED"][i]}</text>
        </g>
      ))}

      {AMBIENT.filter(a => a.tier <= tierMax).map((a, i) => (
        <circle key={"a" + i} cx={a.x} cy={a.y} r={a.r} fill="#2A4A78" opacity={a.o} />
      ))}

      {visE.map(([a, b, s, o], i) => {
        const hot = isHot(o), down = isDown(o);
        const won = complete && hot;
        return (
          <line key={i} x1={N[a].x} y1={N[a].y} x2={N[b].x} y2={N[b].y}
            stroke={won ? "#3DDB8E" : hot ? "#5B9DF5" : down ? "#7A3B36" : "#1C2A3D"}
            strokeWidth={won ? 2.4 : hot ? 2 : 1.2}
            strokeDasharray={won ? "none" : hot ? "7 5" : o.probe ? "2 5" : "none"}
            className={hot && !won ? "ng-flow" : ""}
            opacity={down ? 0.5 : complete && !hot ? 0.3 : 0.95} />
        );
      })}

      {visN.map(n => {
        const st = nodeState(n);
        const isNew = n.s === stage && stage > 0 && n.type !== "frontier";
        const dimLabel = complete && n.type === "dest" && MD.STAGES[stage].dest !== n.dest;
        return (
          <g key={n.id} transform={`translate(${n.x},${n.y})`}>
            {isNew && !complete && <circle r={n.r + 7} fill="none" stroke="#8FB7F0" strokeWidth="1" className="ng-new" />}
            {shape(n)}
            {!mini && n.label ? (
              <text y={n.r + (n.type === "dest" ? 22 : 17)} textAnchor="middle"
                fontFamily="'IBM Plex Mono', monospace"
                fontSize={n.type === "dest" || n.type === "you" ? 10.5 : 9.5}
                fill={st === "dead" ? "#6B4540" : st === "cleared" ? "#7FCFA8" : n.type === "dest" ? "#8FB7F0" : n.type === "you" ? "#F2F6FB" : "#5A6E88"}
                opacity={dimLabel ? 0.35 : 1}
                letterSpacing="0.08em">{n.label}</text>) : null}
          </g>
        );
      })}

      {complete && !mini && (
        <text x="912" y="86" textAnchor="middle" fontFamily="'IBM Plex Mono', monospace" fontSize="11"
          fill="#3DDB8E" letterSpacing="0.22em" fontWeight="600">PUBLISHED</text>
      )}
    </svg>
  );
};

const GraphLegend = ({ stage }) => (
  <div className="ng-legend">
    <span><i className="ng-l-person"></i>person</span>
    <span><i className="ng-l-event"></i>event</span>
    <span><i className="ng-l-org"></i>org</span>
    <span><i className="ng-l-dest"></i>candidate destination</span>
    <span><i className="ng-l-frontier"></i>queued probe</span>
    {stage >= 4 && <span><i className="ng-l-cleared"></i>cleared</span>}
    {stage >= 6 && <span><i className="ng-l-dead"></i>dead end</span>}
    <span className="ng-l-deg">rings: mapped → contacted → committed · earned edges only, no inferred network</span>
  </div>
);

Object.assign(window, { NetGraph, GraphLegend });
