/* ============================================================
   NetroIQ demo — shared components
   ============================================================ */
var useState = React.useState, useEffect = React.useEffect, useRef = React.useRef;

/* ---------------- icon set ---------------- */
const PATHS = {
  overview: '<path d="M3 12h4l2 5 4-12 2 7h6"/>',
  customers: '<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/>',
  sites: '<path d="M3 21h18M5 21V7l8-4v18M19 21V11l-6-4"/>',
  alerts: '<path d="M12 2a7 7 0 0 0-7 7c0 5-2 6-2 6h18s-2-1-2-6a7 7 0 0 0-7-7z"/><path d="M9 19a3 3 0 0 0 6 0"/>',
  health: '<path d="M20.8 5.6a5 5 0 0 0-7.1 0L12 7.3l-1.7-1.7a5 5 0 1 0-7.1 7.1L12 21l8.8-8.3a5 5 0 0 0 0-7.1z"/>',
  reseller: '<rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/>',
  resellers: '<path d="M3 9h18M3 15h18M9 3v18"/><rect x="3" y="3" width="18" height="18" rx="2"/>',
  settings: '<circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-2.81.7 1.65 1.65 0 0 0-1 1.51V22a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 8 20.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .7-2.81 1.65 1.65 0 0 0-1.51-1H2a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 3.6 8a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H8a1.65 1.65 0 0 0 1-1.51V2a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V8a1.65 1.65 0 0 0 1.51 1H22a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/>',
  moon: '<path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z"/>',
  logout: '<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9"/>',
  search: '<circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/>',
  grid: '<rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/>',
  list: '<path d="M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01"/>',
  columns: '<rect x="3" y="3" width="18" height="18" rx="2"/><path d="M9 3v18M15 3v18"/>',
  wall: '<rect x="3" y="3" width="5" height="5"/><rect x="10" y="3" width="5" height="5"/><rect x="17" y="3" width="4" height="5"/><rect x="3" y="10" width="5" height="5"/><rect x="10" y="10" width="5" height="5"/><rect x="17" y="10" width="4" height="5"/>',
  chevdown: '<path d="m6 9 6 6 6-6"/>',
  chevright: '<path d="m9 6 6 6-6 6"/>',
  back: '<path d="M19 12H5M12 19l-7-7 7-7"/>',
  ext: '<path d="M7 17 17 7M9 7h8v8"/>',
  router: '<rect x="2" y="14" width="20" height="6" rx="2"/><path d="M6 17h.01M10 17h4M15 10l3-3M12 7l3-3M9 10V4"/>',
  switch: '<rect x="2" y="6" width="20" height="6" rx="1"/><rect x="2" y="15" width="20" height="4" rx="1"/><path d="M6 9h.01M6 17h.01"/>',
  ap: '<path d="M5 12a7 7 0 0 1 14 0M8.5 12a3.5 3.5 0 0 1 7 0M12 12v8"/>',
  camera: '<path d="M23 7l-7 5 7 5V7z"/><rect x="1" y="5" width="15" height="14" rx="2"/>',
  clock: '<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>',
  location: '<path d="M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0z"/><circle cx="12" cy="10" r="3"/>',
  wifi: '<path d="M5 12.5a10 10 0 0 1 14 0M8.5 15.8a5 5 0 0 1 7 0M12 19h.01"/>',
  ethernet: '<rect x="3" y="8" width="18" height="11" rx="2"/><path d="M7 8V5M17 8V5M12 19v-3"/>',
  refresh: '<path d="M21 12a9 9 0 1 1-9-9"/><path d="M21 3v6h-6"/>',
  block: '<circle cx="12" cy="12" r="9"/><path d="m5 5 14 14"/>',
  kick: '<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9"/>',
  download: '<path d="M12 3v12M7 10l5 5 5-5M5 21h14"/>',
  upload: '<path d="M12 21V9M7 14l5-5 5 5M5 3h14"/>',
  shield: '<path d="M12 2 4 7v5c0 5 3.5 8 8 9 4.5-1 8-4 8-9V7l-8-4z"/>',
  topology: '<circle cx="6" cy="6" r="2"/><circle cx="18" cy="6" r="2"/><circle cx="12" cy="18" r="2"/><path d="M6 8v3a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V8M12 13v3"/>',
  ai: '<path d="M12 2a3 3 0 0 0-3 3v1a3 3 0 0 0-3 3 3 3 0 0 0 0 6 3 3 0 0 0 3 3 3 3 0 0 0 6 0 3 3 0 0 0 3-3 3 3 0 0 0 0-6 3 3 0 0 0-3-3V5a3 3 0 0 0-3-3z"/>',
  globe: '<circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3c2.5 2.5 3.8 5.7 3.8 9S14.5 18.5 12 21c-2.5-2.5-3.8-5.7-3.8-9S9.5 5.5 12 3z"/>',
  zap: '<path d="M13 2 3 14h7l-1 8 10-12h-7l1-8z"/>',
  check: '<path d="m5 13 4 4L19 7"/>',
  x: '<path d="M18 6 6 18M6 6l12 12"/>',
  menu: '<path d="M3 12h18M3 6h18M3 18h18"/>',
  plus: '<path d="M12 5v14M5 12h14"/>',
  file: '<path d="M14 2v6h6"/><path d="M4 22V4a2 2 0 0 1 2-2h8l6 6v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2z"/>',
  wrench: '<path d="M14.7 6.3a4 4 0 0 0-5.4 5.3L3 18v3h3l6.4-6.4a4 4 0 0 0 5.3-5.4l-2.6 2.6-2.1-.5-.5-2.1z"/>',
  chart: '<path d="M3 3v18h18M7 14l3-4 3 3 4-6"/>',
  tag: '<path d="M20 10 13 3H4v9l7 7 9-9z"/><circle cx="8" cy="8" r="1.5"/>',
  console: '<rect x="2" y="3" width="20" height="14" rx="2"/><path d="m7 8 3 2-3 2M13 12h4M8 21h8"/>',
  prompt: '<path d="m4 17 6-5-6-5M12 19h8"/>',
};
function Icon({ name, style }) {
  const p = PATHS[name] || '';
  return <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"
    strokeLinecap="round" strokeLinejoin="round" style={style}
    dangerouslySetInnerHTML={{ __html: p }} />;
}

/* ---------------- sidebar ---------------- */
function Sidebar({ route, go, open }) {
  const item = (id, icon, label, count) => (
    <button className={"nav-item" + (route.split("/")[0] === id ? " active" : "")} onClick={() => go(id)}>
      <Icon name={icon} /> {label}
      {count != null && <span className={"ct" + (count.crit ? " crit" : "")}>{count.n}</span>}
    </button>
  );
  return (
    <aside className={"side" + (open ? " open" : "")}>
      <div className="side-brand"><img src="../assets/logo-full-white.png" alt="inetro" /></div>
      <div className="side-grp">MSP: Dashboard</div>
      <div className="side-sec">
        {item("overview", "overview", "Live Overview")}
        {item("customers", "customers", "Customers")}
        {item("sites", "sites", "Sites")}
        {item("alerts", "alerts", "Active Alerts", { n: 7, crit: true })}
        {item("health", "health", "Health")}
      </div>
      <div className="side-foot">
        <div className="fitem" onClick={() => go("settings")}><Icon name="settings" /> Settings</div>
        <div className="fitem"><Icon name="moon" /> Dark Mode</div>
        <div className="fitem" onClick={() => go("overview")}><Icon name="logout" /> Logout</div>
      </div>
    </aside>
  );
}

/* ---------------- topbar / breadcrumbs ---------------- */
function Topbar({ crumbs, go, onMenu }) {
  return (
    <div className="topbar">
      <button className="menu-btn" onClick={onMenu}><Icon name="menu" /></button>
      <div className="crumbs">
        {crumbs.map((c, i) => (
          <React.Fragment key={i}>
            {i > 0 && <span className="sep"><Icon name="chevright" style={{ width: 13, height: 13 }} /></span>}
            {c.to ? <a onClick={() => go(c.to)}>{c.label}</a> : <span className="cur">{c.label}</span>}
          </React.Fragment>
        ))}
      </div>
    </div>
  );
}

/* ---------------- sparkline ---------------- */
function Sparkline({ data, hiAt }) {
  return <div className="spark">{data.map((h, i) => <i key={i} className={i === hiAt ? "hi" : ""} style={{ height: h + "%" }} />)}</div>;
}

/* ---------------- smoothing helper ---------------- */
function smoothPath(pts) {
  if (pts.length < 2) return "";
  let d = `M ${pts[0][0]} ${pts[0][1]}`;
  for (let i = 0; i < pts.length - 1; i++) {
    const p0 = pts[i - 1] || pts[i], p1 = pts[i], p2 = pts[i + 1], p3 = pts[i + 2] || p2;
    const c1x = p1[0] + (p2[0] - p0[0]) / 6, c1y = p1[1] + (p2[1] - p0[1]) / 6;
    const c2x = p2[0] - (p3[0] - p1[0]) / 6, c2y = p2[1] - (p3[1] - p1[1]) / 6;
    d += ` C ${c1x.toFixed(1)} ${c1y.toFixed(1)} ${c2x.toFixed(1)} ${c2y.toFixed(1)} ${p2[0].toFixed(1)} ${p2[1].toFixed(1)}`;
  }
  return d;
}

/* ---------------- world map ---------------- */
const MAP_DOTS = (() => {
  const clusters = [
    // [xMin,xMax,yMin,yMax, count]
    [17, 35, 36, 62, 26],   // North America
    [45, 55, 28, 46, 14],   // Europe
    [57, 67, 42, 54, 6],    // Middle East
    [68, 80, 48, 64, 5],    // Asia
    [78, 86, 64, 73, 3],    // Australia
  ];
  let s = 999, r = () => { s = (s * 1103515245 + 12345) & 0x7fffffff; return s / 0x7fffffff; };
  const dots = [];
  clusters.forEach(([x0, x1, y0, y1, n]) => {
    for (let i = 0; i < n; i++) {
      const v = r();
      const st = v < 0.74 ? "on" : v < 0.9 ? "deg" : "dn";
      dots.push({ x: x0 + r() * (x1 - x0), y: y0 + r() * (y1 - y0), st, sz: r() < 0.3 ? 6 : 9, pulse: r() < 0.18 });
    }
  });
  return dots;
})();
function WorldMap() {
  const m = DEMO.metrics.map;
  return (
    <div className="map">
      <div className="map-h">
        <div className="map-title"><span className="dot on" /> Global Infrastructure <small>{m.total} of {m.total} locations</small></div>
        <div className="map-leg">
          <span className="ok"><i /> Healthy ({m.healthy})</span>
          <span className="dg"><i /> Degraded ({m.degraded})</span>
          <span className="dn"><i /> Down ({m.down})</span>
        </div>
      </div>
      <div className="map-zoom"><button>+</button><button>−</button></div>
      {MAP_DOTS.map((d, i) => (
        <span key={i} className={"mdot " + d.st + (d.pulse ? " pulse" : "")}
          style={{ left: d.x + "%", top: d.y + "%", width: d.sz, height: d.sz }} title={d.st} />
      ))}
    </div>
  );
}

/* ---------------- ISP health chart (static 7d) ---------------- */
const ISP_SERIES = (() => {
  let s = 4242, r = () => { s = (s * 1103515245 + 12345) & 0x7fffffff; return s / 0x7fffffff; };
  const n = 80, avg = [], max = [], loss = [];
  for (let i = 0; i < n; i++) {
    const base = 8 + Math.sin(i / 6) * 3 + r() * 4;
    const spike = r() < 0.08 ? r() * 28 : 0;
    avg.push(base + spike * 0.4);
    max.push(base + 8 + r() * 18 + spike);
    loss.push(r() < 0.12 ? r() * 1 : 0);
  }
  return { avg, max, loss, n };
})();
function ISPChart() {
  const W = 1000, H = 240, { avg, max, loss, n } = ISP_SERIES;
  const maxMs = 80;
  const xat = i => (i / (n - 1)) * W;
  const yms = v => H - Math.min(v, maxMs) / maxMs * H;
  const uptimeArea = `M0 ${H * 0.02} ` + avg.map((_, i) => `L ${xat(i)} ${H * 0.02}`).join(" ") + ` L ${W} ${H} L 0 ${H} Z`;
  const avgPts = avg.map((v, i) => [xat(i), yms(v)]);
  const maxPts = max.map((v, i) => [xat(i), yms(v)]);
  const labels = ["Sun 9PM", "Mon 6PM", "Tue 3PM", "Wed 12PM", "Thu 9AM", "Fri 6AM", "Sat 3AM", "Sun 12AM"];
  return (
    <div>
      <svg viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="none" style={{ width: "100%", height: 230, display: "block" }}>
        <defs><linearGradient id="upg" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor="rgba(28,162,126,.30)" /><stop offset="100%" stopColor="rgba(28,162,126,.02)" /></linearGradient></defs>
        {[0.25, 0.5, 0.75].map(g => <line key={g} x1="0" y1={H * g} x2={W} y2={H * g} stroke="#eceef3" strokeWidth="1" />)}
        <path d={uptimeArea} fill="url(#upg)" />
        <path d={smoothPath(maxPts)} fill="none" stroke="#b9bdf0" strokeWidth="1.6" strokeDasharray="5 4" />
        <path d={smoothPath(avgPts)} fill="none" stroke="#1c2452" strokeWidth="2.2" />
        {loss.map((v, i) => v > 0 ? <circle key={i} cx={xat(i)} cy={H - 4} r={2.5 + v * 3} fill="#e23d3d" opacity="0.8" /> : null)}
      </svg>
      <div className="chart-x">{labels.map(l => <span key={l}>{l}</span>)}</div>
      <div className="legend">
        <span><i style={{ background: "#1c2452" }} /> Avg Latency (ms)</span>
        <span><i style={{ background: "#b9bdf0" }} /> Max Latency (ms)</span>
        <span><i style={{ background: "#e23d3d" }} /> Packet Loss (%)</span>
        <span><i style={{ background: "#1CA27E" }} /> Uptime (%)</span>
      </div>
    </div>
  );
}

/* ---------------- LIVE WAN throughput (animated) ---------------- */
function LiveThroughput() {
  const [samples, setSamples] = useState(() => [{ dl: 0.22, ul: 0.05, t: Date.now() }]);
  const walk = useRef({ dl: 0.22, ul: 0.05 });
  useEffect(() => {
    const id = setInterval(() => {
      const w = walk.current;
      const spikeDl = Math.random() < 0.18 ? Math.random() * 1.8 : 0;
      const spikeUl = Math.random() < 0.12 ? Math.random() * 0.7 : 0;
      w.dl = Math.max(0.03, Math.min(2.6, w.dl + (Math.random() - 0.45) * 0.25 + spikeDl - (w.dl > 1 ? 0.3 : 0)));
      w.ul = Math.max(0.02, Math.min(1.2, w.ul + (Math.random() - 0.45) * 0.12 + spikeUl - (w.ul > 0.6 ? 0.15 : 0)));
      setSamples(s => [...s.slice(-44), { dl: +w.dl.toFixed(2), ul: +w.ul.toFixed(2), t: Date.now() }]);
    }, 1500);
    return () => clearInterval(id);
  }, []);

  const W = 1000, H = 260;
  const n = samples.length;
  const maxV = Math.max(0.3, ...samples.map(s => Math.max(s.dl, s.ul))) * 1.15;
  const xat = i => n <= 1 ? 0 : (i / (n - 1)) * W;
  const yat = v => H - (v / maxV) * H;
  const dlPts = samples.map((s, i) => [xat(i), yat(s.dl)]);
  const ulPts = samples.map((s, i) => [xat(i), yat(s.ul)]);
  const dlArea = n > 1 ? smoothPath(dlPts) + ` L ${W} ${H} L 0 ${H} Z` : "";
  const last = samples[n - 1] || { dl: 0, ul: 0 };
  const peakDl = Math.max(...samples.map(s => s.dl));
  const peakUl = Math.max(...samples.map(s => s.ul));
  const fmtT = t => new Date(t).toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit", second: "2-digit" });

  return (
    <div>
      <div className="tp-note">Actual WAN traffic sampled every 15s — {n} sample{n !== 1 ? "s" : ""}</div>
      <div className="tp-stats">
        <div className="tp-stat"><div className="k">Current ↓</div><div className="v dl">{last.dl.toFixed(2)} Mbps</div></div>
        <div className="tp-stat"><div className="k">Current ↑</div><div className="v ul">{last.ul.toFixed(2)} Mbps</div></div>
        <div className="tp-stat"><div className="k">Peak ↓</div><div className="v dl">{peakDl.toFixed(2)} Mbps</div></div>
        <div className="tp-stat"><div className="k">Peak ↑</div><div className="v ul">{peakUl.toFixed(2)} Mbps</div></div>
      </div>
      <svg viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="none" style={{ width: "100%", height: 250, display: "block" }}>
        <defs><linearGradient id="tpg" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor="rgba(28,162,126,.34)" /><stop offset="100%" stopColor="rgba(28,162,126,.03)" /></linearGradient></defs>
        {[0.25, 0.5, 0.75].map(g => <line key={g} x1="0" y1={H * g} x2={W} y2={H * g} stroke="#eceef3" strokeWidth="1" strokeDasharray="3 4" />)}
        {n > 1 && <path d={dlArea} fill="url(#tpg)" />}
        {n > 1 && <path d={smoothPath(dlPts)} fill="none" stroke="#1CA27E" strokeWidth="2.4" />}
        {n > 1 && <path d={smoothPath(ulPts)} fill="none" stroke="#221C84" strokeWidth="2.2" />}
        {n > 0 && <circle cx={xat(n - 1)} cy={yat(last.dl)} r="4" fill="#1CA27E" />}
        {n > 0 && <circle cx={xat(n - 1)} cy={yat(last.ul)} r="4" fill="#221C84" />}
      </svg>
      <div className="chart-x"><span>{fmtT(samples[0].t)}</span><span>{fmtT(last.t)}</span></div>
      <div className="legend">
        <span><i style={{ background: "#1CA27E" }} /> Download (↓)</span>
        <span><i style={{ background: "#221C84" }} /> Upload (↑)</span>
      </div>
    </div>
  );
}

Object.assign(window, { Icon, Sidebar, Topbar, Sparkline, WorldMap, ISPChart, LiveThroughput, smoothPath });
