/* =========================================================
   NETRA AI — signature visualizations
   - RadialCorrelation : sensors/cameras around a ring, pulses link events
   - IsoFloorplan      : isometric floor map with live device dots
   - TimelineRiver     : multi-lane event timeline that converges on incidents
   - IrisRing          : circular activity dashboard
   - SimFeed           : fake camera feed (canvas) with moving "people"
   ========================================================= */

/* ============ RadialCorrelation ============ */
const RadialCorrelation = ({ size = 460 }) => {
  const cx = size / 2, cy = size / 2;
  const Rout = size * 0.42, Rin = size * 0.18;

  const nodes = React.useMemo(() => {
    const cams = ["CAM-001","CAM-003","CAM-004","CAM-005","CAM-007","CAM-008","CAM-010","CAM-011"];
    const snrs = ["SNS-021","SNS-024","SNS-031","RDR-007","RDR-008","RDR-009"];
    const all = [...cams.map(id => ({id, kind:"cam"})), ...snrs.map(id => ({id, kind:"snr"}))];
    return all.map((n, i) => {
      const a = (i / all.length) * Math.PI * 2 - Math.PI / 2;
      return { ...n, x: cx + Math.cos(a) * Rout, y: cy + Math.sin(a) * Rout, a };
    });
  }, [size]);

  // animated links — random pairs of nodes get a pulse line through center
  const [pulses, setPulses] = React.useState([]);
  React.useEffect(() => {
    let id = 0;
    const t = setInterval(() => {
      const a = nodes[Math.floor(Math.random() * nodes.length)];
      let b; do { b = nodes[Math.floor(Math.random() * nodes.length)]; } while (b.id === a.id);
      const sev = Math.random() < 0.15 ? "crit" : Math.random() < 0.35 ? "warn" : "info";
      const pulse = { id: id++, a, b, sev, t: Date.now() };
      setPulses(p => [...p, pulse].slice(-10));
      setTimeout(() => setPulses(p => p.filter(x => x.id !== pulse.id)), 2400);
    }, 700);
    return () => clearInterval(t);
  }, [nodes]);

  const sevColor = s => s === "crit" ? "var(--crit)" : s === "warn" ? "var(--warn)" : "var(--iris)";

  return (
    <svg viewBox={`0 0 ${size} ${size}`} width="100%" style={{ display: "block" }}>
      <defs>
        <radialGradient id="rc-core" cx="50%" cy="50%" r="50%">
          <stop offset="0%"  stopColor="#4dd6ff" stopOpacity="0.4" />
          <stop offset="60%" stopColor="#4dd6ff" stopOpacity="0.08" />
          <stop offset="100%" stopColor="#4dd6ff" stopOpacity="0" />
        </radialGradient>
        <filter id="rc-glow"><feGaussianBlur stdDeviation="2.5" /></filter>
      </defs>

      {/* concentric rings */}
      {[0.95, 0.78, 0.58, 0.4].map((k, i) => (
        <circle key={i} cx={cx} cy={cy} r={Rout * k} fill="none"
          stroke="rgba(255,255,255,0.05)" strokeWidth={i === 0 ? 1 : 0.6}
          strokeDasharray={i === 0 ? "" : "2 6"} />
      ))}

      {/* radial spokes */}
      {Array.from({length: 12}).map((_, i) => {
        const a = (i / 12) * Math.PI * 2;
        const x1 = cx + Math.cos(a) * Rin, y1 = cy + Math.sin(a) * Rin;
        const x2 = cx + Math.cos(a) * Rout, y2 = cy + Math.sin(a) * Rout;
        return <line key={i} x1={x1} y1={y1} x2={x2} y2={y2} stroke="rgba(255,255,255,0.04)" />;
      })}

      {/* center core */}
      <circle cx={cx} cy={cy} r={Rin * 1.4} fill="url(#rc-core)" />
      <circle cx={cx} cy={cy} r={Rin} fill="none" stroke="var(--iris)" strokeWidth="1" strokeOpacity="0.4" />
      <circle cx={cx} cy={cy} r={Rin * 0.65} fill="none" stroke="var(--saffron)" strokeWidth="0.6" strokeOpacity="0.5" />
      <circle cx={cx} cy={cy} r={6} fill="var(--iris)" filter="url(#rc-glow)" />
      <text x={cx} y={cy - Rin - 12} textAnchor="middle"
            style={{font: "10px var(--font-mono)", fill: "var(--ink-3)", letterSpacing: "0.2em"}}>
        NETRA CORE
      </text>
      <text x={cx} y={cy + 4} textAnchor="middle"
            style={{font: "9px var(--font-mono)", fill: "var(--bg-0)", letterSpacing: "0.1em"}}>
        AI
      </text>

      {/* pulses */}
      {pulses.map(p => {
        const age = (Date.now() - p.t) / 2400;
        const opacity = Math.max(0, 1 - age);
        const c = sevColor(p.sev);
        return (
          <g key={p.id} opacity={opacity}>
            <path d={`M ${p.a.x} ${p.a.y} Q ${cx} ${cy} ${p.b.x} ${p.b.y}`}
                  fill="none" stroke={c} strokeWidth="1.2" strokeOpacity="0.8" />
            <circle cx={cx} cy={cy} r={3 + age * 60} fill="none" stroke={c} strokeOpacity={opacity * 0.4} />
          </g>
        );
      })}

      {/* nodes */}
      {nodes.map(n => {
        const c = n.kind === "cam" ? "var(--iris)" : "var(--saffron)";
        const angleDeg = (n.a * 180) / Math.PI;
        const labelX = cx + Math.cos(n.a) * (Rout + 22);
        const labelY = cy + Math.sin(n.a) * (Rout + 22);
        return (
          <g key={n.id}>
            <circle cx={n.x} cy={n.y} r="5" fill={c} />
            <circle cx={n.x} cy={n.y} r="9" fill="none" stroke={c} strokeOpacity="0.3" />
            <text x={labelX} y={labelY} textAnchor="middle" dy="0.35em"
                  style={{font: "9px var(--font-mono)", fill: "var(--ink-2)", letterSpacing: "0.1em"}}>
              {n.id}
            </text>
          </g>
        );
      })}
    </svg>
  );
};

/* ============ IsoFloorplan ============ */
const IsoFloorplan = ({ floor, height = 460, onPoint }) => {
  // isometric projection: x' = (x - y) * tw/2, y' = (x + y) * th/2
  const tw = 26, th = 13;
  const W = (floor.w + floor.h) * tw / 2 + 80;
  const H = (floor.w + floor.h) * th / 2 + 80;
  const proj = (x, y) => [(x - y) * tw / 2 + W / 2, (x + y) * th / 2 + 20];

  const roomKindColor = k => ({
    common:     "rgba(122,162,255,0.08)",
    transit:    "rgba(255,255,255,0.04)",
    restricted: "rgba(255,61,110,0.10)",
    office:     "rgba(77,214,255,0.06)",
    perimeter:  "rgba(240,167,58,0.08)",
  }[k] || "rgba(255,255,255,0.04)");

  const roomKindStroke = k => ({
    common:     "rgba(122,162,255,0.30)",
    transit:    "rgba(255,255,255,0.15)",
    restricted: "rgba(255,61,110,0.35)",
    office:     "rgba(77,214,255,0.25)",
    perimeter:  "rgba(240,167,58,0.30)",
  }[k] || "rgba(255,255,255,0.15)");

  return (
    <svg viewBox={`0 0 ${W} ${H}`} width="100%" height={height}>
      <defs>
        <filter id="iso-shadow"><feGaussianBlur stdDeviation="3" /></filter>
      </defs>

      {/* base grid */}
      {Array.from({length: floor.w + 1}).map((_, x) => {
        const [x1, y1] = proj(x, 0); const [x2, y2] = proj(x, floor.h);
        return <line key={"vx"+x} x1={x1} y1={y1} x2={x2} y2={y2} stroke="rgba(255,255,255,0.03)" />;
      })}
      {Array.from({length: floor.h + 1}).map((_, y) => {
        const [x1, y1] = proj(0, y); const [x2, y2] = proj(floor.w, y);
        return <line key={"vy"+y} x1={x1} y1={y1} x2={x2} y2={y2} stroke="rgba(255,255,255,0.03)" />;
      })}

      {/* rooms */}
      {floor.rooms.map(r => {
        const a = proj(r.x, r.y);
        const b = proj(r.x + r.w, r.y);
        const c = proj(r.x + r.w, r.y + r.h);
        const d = proj(r.x, r.y + r.h);
        const cx = (a[0] + c[0]) / 2, cy = (a[1] + c[1]) / 2;
        return (
          <g key={r.id}>
            <polygon points={`${a} ${b} ${c} ${d}`}
                     fill={roomKindColor(r.kind)} stroke={roomKindStroke(r.kind)} strokeWidth="1" />
            <text x={cx} y={cy} textAnchor="middle" dy="0.3em"
                  style={{font: "10px var(--font-mono)", fill: "var(--ink-2)", letterSpacing: "0.14em", textTransform: "uppercase"}}>
              {r.name}
            </text>
          </g>
        );
      })}

      {/* heatmap-ish risk blobs */}
      {floor.points.filter(p => p.status === "crit" || p.status === "warn").map(p => {
        const [px, py] = proj(p.x, p.y);
        return <circle key={"h"+p.id} cx={px} cy={py} r="34"
                  fill={p.status === "crit" ? "rgba(255,61,110,0.25)" : "rgba(240,167,58,0.18)"}
                  filter="url(#iso-shadow)" />;
      })}

      {/* devices */}
      {floor.points.map(p => {
        const [px, py] = proj(p.x, p.y);
        const c = p.status === "crit" ? "var(--crit)" : p.status === "warn" ? "var(--warn)" : p.status === "degr" ? "var(--warn)" : p.kind === "cam" ? "var(--iris)" : p.kind === "rdr" ? "var(--saffron)" : "var(--good)";
        return (
          <g key={p.id} style={{cursor: "pointer"}} onClick={() => onPoint && onPoint(p)}>
            {p.status === "crit" && (
              <circle cx={px} cy={py} r="14" fill="none" stroke={c} strokeOpacity="0.4">
                <animate attributeName="r" from="6" to="22" dur="1.4s" repeatCount="indefinite" />
                <animate attributeName="opacity" from="0.7" to="0" dur="1.4s" repeatCount="indefinite" />
              </circle>
            )}
            <circle cx={px} cy={py} r="6" fill="var(--bg-0)" stroke={c} strokeWidth="1.5" />
            <circle cx={px} cy={py} r="2.5" fill={c} />
            <text x={px + 9} y={py - 8} style={{font: "9px var(--font-mono)", fill: "var(--ink-2)"}}>
              {p.id}
            </text>
          </g>
        );
      })}

      {/* legend */}
      <g transform={`translate(20, ${H - 70})`}>
        <text x="0" y="0" style={{font: "9px var(--font-mono)", fill: "var(--ink-3)", letterSpacing: "0.16em"}}>LEGEND</text>
        {[
          ["Camera", "var(--iris)"], ["Sensor", "var(--good)"], ["Reader", "var(--saffron)"],
          ["Warn", "var(--warn)"], ["Critical", "var(--crit)"],
        ].map(([lbl, c], i) => (
          <g key={lbl} transform={`translate(${(i % 3) * 80}, ${20 + Math.floor(i / 3) * 18})`}>
            <circle cx="6" cy="0" r="4" fill={c} />
            <text x="14" y="3" style={{font: "10px var(--font-mono)", fill: "var(--ink-2)"}}>{lbl}</text>
          </g>
        ))}
      </g>
    </svg>
  );
};

/* ============ TimelineRiver ============ */
const TimelineRiver = ({ events, height = 280 }) => {
  const lanes = [
    { id: "camera", lbl: "CAMERA",  color: "var(--iris)"    },
    { id: "badge",  lbl: "BADGE",   color: "var(--saffron)" },
    { id: "door",   lbl: "DOOR",    color: "var(--good)"    },
    { id: "ai",     lbl: "AI",      color: "var(--info)"    },
    { id: "system", lbl: "SYSTEM",  color: "var(--ink-2)"   },
  ];
  const padL = 90, padR = 30, padT = 16, padB = 24;
  const w = 900;
  const innerW = w - padL - padR;
  const laneH = (height - padT - padB) / lanes.length;
  // map t -> x (assume window of last event, first event)
  const tToSec = ts => {
    const [h, m, s] = ts.split(":").map(Number);
    return h*3600 + m*60 + s;
  };
  const ts = events.map(e => tToSec(e.t));
  const tMin = Math.min(...ts), tMax = Math.max(...ts);
  const span = Math.max(tMax - tMin, 1);
  const xFor = t => padL + ((t - tMin) / span) * innerW;
  const yFor = lane => padT + lanes.findIndex(l => l.id === lane) * laneH + laneH / 2;
  const sevColor = s => s === "crit" ? "var(--crit)" : s === "warn" ? "var(--warn)" : "var(--iris)";

  // convergence point — the "ai system" event marks the incident creation
  const convT = tToSec(events.find(e => e.lane === "system" && e.label.toLowerCase().includes("inc"))?.t || events[events.length-1].t);
  const convX = xFor(convT);

  return (
    <svg viewBox={`0 0 ${w} ${height}`} width="100%" style={{ display: "block" }}>
      {/* lanes */}
      {lanes.map((l, i) => (
        <g key={l.id}>
          <line x1={padL} y1={padT + i*laneH + laneH/2} x2={w-padR} y2={padT + i*laneH + laneH/2}
                stroke="rgba(255,255,255,0.04)" strokeDasharray="2 6" />
          <text x={padL - 12} y={padT + i*laneH + laneH/2 + 3} textAnchor="end"
                style={{font: "9px var(--font-mono)", fill: "var(--ink-3)", letterSpacing: "0.16em"}}>
            {l.lbl}
          </text>
        </g>
      ))}

      {/* convergence node + funnel */}
      <circle cx={convX} cy={height - padB - 6} r="14" fill="none" stroke="var(--crit)" strokeOpacity="0.4" />
      <circle cx={convX} cy={height - padB - 6} r="6" fill="var(--crit)" />
      <text x={convX} y={height - 4} textAnchor="middle" style={{font: "9px var(--font-mono)", fill: "var(--crit)", letterSpacing: "0.14em"}}>INCIDENT</text>

      {/* event lines to convergence */}
      {events.map((e, i) => {
        const x = xFor(tToSec(e.t)), y = yFor(e.lane);
        const c = sevColor(e.sev);
        return (
          <g key={i}>
            <path d={`M ${x} ${y} C ${x} ${height - padB - 6}, ${convX} ${y}, ${convX} ${height - padB - 6}`}
                  fill="none" stroke={c} strokeOpacity="0.18" strokeWidth="1" />
          </g>
        );
      })}

      {/* events */}
      {events.map((e, i) => {
        const x = xFor(tToSec(e.t)), y = yFor(e.lane);
        const c = sevColor(e.sev);
        return (
          <g key={"e"+i}>
            <circle cx={x} cy={y} r="5" fill={c} />
            <circle cx={x} cy={y} r="5" fill="none" stroke={c} strokeOpacity="0.3" strokeWidth="6" />
            <text x={x} y={y - 12} textAnchor="middle"
                  style={{font: "9px var(--font-mono)", fill: "var(--ink-2)"}}>{e.t.slice(3)}</text>
          </g>
        );
      })}
    </svg>
  );
};

/* ============ IrisRing — circular activity dashboard ============ */
const IrisRing = ({ data, size = 380, label = "LAST 24 H" }) => {
  // data: array of {alerts, access} per hour
  const cx = size/2, cy = size/2;
  const Rmax = size * 0.45, Rmin = size * 0.16;
  const sliceA = (Math.PI * 2) / data.length;
  const maxA = Math.max(...data.map(d => d.alerts), 1);
  const maxX = Math.max(...data.map(d => d.access), 1);

  return (
    <svg viewBox={`0 0 ${size} ${size}`} width="100%" style={{display:"block"}}>
      <defs>
        <radialGradient id="ir-core" cx="50%" cy="50%" r="50%">
          <stop offset="0%" stopColor="#06080d" />
          <stop offset="100%" stopColor="#0a1828" />
        </radialGradient>
      </defs>
      {/* base ring */}
      <circle cx={cx} cy={cy} r={Rmax} fill="none" stroke="rgba(255,255,255,0.04)" />
      <circle cx={cx} cy={cy} r={(Rmax + Rmin)/2} fill="none" stroke="rgba(255,255,255,0.04)" strokeDasharray="2 6" />
      <circle cx={cx} cy={cy} r={Rmin} fill="url(#ir-core)" stroke="rgba(77,214,255,0.4)" />

      {/* spokes / hour ticks */}
      {data.map((_, i) => {
        const a = i * sliceA - Math.PI / 2;
        const x1 = cx + Math.cos(a) * Rmin, y1 = cy + Math.sin(a) * Rmin;
        const x2 = cx + Math.cos(a) * Rmax, y2 = cy + Math.sin(a) * Rmax;
        return <line key={"sp"+i} x1={x1} y1={y1} x2={x2} y2={y2} stroke="rgba(255,255,255,0.04)" />;
      })}

      {/* access bars (outer ring, saffron) */}
      {data.map((d, i) => {
        const a0 = i * sliceA - Math.PI / 2 + sliceA * 0.1;
        const a1 = (i+1) * sliceA - Math.PI / 2 - sliceA * 0.1;
        const len = (d.access / maxX) * (Rmax - Rmin) * 0.55;
        const r1 = (Rmax + Rmin)/2 + 4, r2 = r1 + len;
        const xa = cx + Math.cos(a0) * r1, ya = cy + Math.sin(a0) * r1;
        const xb = cx + Math.cos(a1) * r1, yb = cy + Math.sin(a1) * r1;
        const xc = cx + Math.cos(a1) * r2, yc = cy + Math.sin(a1) * r2;
        const xd = cx + Math.cos(a0) * r2, yd = cy + Math.sin(a0) * r2;
        return <path key={"ax"+i} d={`M${xa} ${ya} L${xb} ${yb} L${xc} ${yc} L${xd} ${yd}Z`}
                   fill="var(--saffron)" fillOpacity="0.65" />;
      })}

      {/* alert bars (inner ring, iris cyan, w/ crit overlay) */}
      {data.map((d, i) => {
        const a0 = i * sliceA - Math.PI / 2 + sliceA * 0.15;
        const a1 = (i+1) * sliceA - Math.PI / 2 - sliceA * 0.15;
        const len = (d.alerts / maxA) * (Rmax - Rmin) * 0.42;
        const r1 = Rmin + 4, r2 = r1 + len;
        const xa = cx + Math.cos(a0) * r1, ya = cy + Math.sin(a0) * r1;
        const xb = cx + Math.cos(a1) * r1, yb = cy + Math.sin(a1) * r1;
        const xc = cx + Math.cos(a1) * r2, yc = cy + Math.sin(a1) * r2;
        const xd = cx + Math.cos(a0) * r2, yd = cy + Math.sin(a0) * r2;
        const fill = d.crit > 0 ? "var(--crit)" : "var(--iris)";
        return <path key={"al"+i} d={`M${xa} ${ya} L${xb} ${yb} L${xc} ${yc} L${xd} ${yd}Z`}
                   fill={fill} fillOpacity={d.crit > 0 ? 0.95 : 0.75} />;
      })}

      {/* hour labels — every 6h */}
      {[0,6,12,18].map(h => {
        const a = h * sliceA - Math.PI / 2;
        const x = cx + Math.cos(a) * (Rmax + 14);
        const y = cy + Math.sin(a) * (Rmax + 14);
        return <text key={h} x={x} y={y} textAnchor="middle" dy="0.35em"
                     style={{font: "9px var(--font-mono)", fill: "var(--ink-3)", letterSpacing: "0.16em"}}>
                  {String(h).padStart(2,"0")}:00
               </text>;
      })}

      {/* center stats */}
      <text x={cx} y={cy - 14} textAnchor="middle"
            style={{font: "9px var(--font-mono)", fill: "var(--ink-3)", letterSpacing: "0.2em"}}>{label}</text>
      <text x={cx} y={cy + 6} textAnchor="middle"
            style={{font: "500 22px var(--font-display)", fill: "var(--ink-0)", letterSpacing: "-0.02em"}}>
        {data.reduce((s,d)=>s+d.alerts,0)}
      </text>
      <text x={cx} y={cy + 22} textAnchor="middle"
            style={{font: "9px var(--font-mono)", fill: "var(--ink-3)", letterSpacing: "0.16em"}}>ALERTS</text>
    </svg>
  );
};

Object.assign(window, { RadialCorrelation, IsoFloorplan, TimelineRiver, IrisRing });
