// Live spectrum visualization — wide LTE band with narrow NB-IoT carrier highlighted.
// The narrow carrier is what gives the listing its conceptual hook.

const { useEffect, useRef, useState } = React;

function Spectrum({ height = 180, accent = "var(--accent)", live = true }) {
  const ref = useRef(null);
  const rafRef = useRef(0);
  const startRef = useRef(performance.now());

  useEffect(() => {
    const canvas = ref.current;
    if (!canvas) return;
    const ctx = canvas.getContext("2d");
    const dpr = Math.min(window.devicePixelRatio || 1, 2);

    const resize = () => {
      const r = canvas.getBoundingClientRect();
      canvas.width = r.width * dpr;
      canvas.height = r.height * dpr;
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
    };
    resize();
    const ro = new ResizeObserver(resize);
    ro.observe(canvas);

    const accentColor = getComputedStyle(document.documentElement)
      .getPropertyValue("--accent").trim() || "#f0a040";
    const lineColor = getComputedStyle(document.documentElement)
      .getPropertyValue("--line-2").trim() || "#3a3f4a";
    const fgColor = getComputedStyle(document.documentElement)
      .getPropertyValue("--fg-2").trim() || "#cbcbc4";

    const draw = (now) => {
      const t = (now - startRef.current) / 1000;
      const { width, height: h } = canvas.getBoundingClientRect();
      ctx.clearRect(0, 0, width, h);

      // baseline grid
      ctx.strokeStyle = lineColor;
      ctx.lineWidth = 1;
      ctx.globalAlpha = 0.4;
      ctx.beginPath();
      for (let i = 0; i < 5; i++) {
        const y = (h / 4) * i + 0.5;
        ctx.moveTo(0, y); ctx.lineTo(width, y);
      }
      ctx.stroke();
      ctx.globalAlpha = 1;

      // wide-band noise floor (LTE neighbours)
      const bars = 180;
      const barW = width / bars;
      ctx.fillStyle = lineColor;
      for (let i = 0; i < bars; i++) {
        const x = i * barW;
        const seed = Math.sin(i * 12.9898 + 4.1414) * 43758.5453;
        const r = (seed - Math.floor(seed));
        const wob = live ? Math.sin(t * 2 + i * 0.3) * 0.15 : 0;
        const v = (0.18 + r * 0.32 + wob) * h * 0.55;
        ctx.fillRect(x, h - v, Math.max(1, barW - 1), v);
      }

      // narrow band (NB-IoT — 200 kHz carrier) — the hero peak
      const center = width * 0.5;
      const bandW = width * 0.06;
      const peakH = h * (0.78 + (live ? Math.sin(t * 3) * 0.08 : 0));

      // glow
      const grad = ctx.createRadialGradient(center, h - peakH * 0.4, 4, center, h - peakH * 0.4, bandW * 2);
      grad.addColorStop(0, accentColor);
      grad.addColorStop(1, "transparent");
      ctx.globalAlpha = 0.35;
      ctx.fillStyle = grad;
      ctx.fillRect(center - bandW * 2, 0, bandW * 4, h);
      ctx.globalAlpha = 1;

      // narrow bars
      ctx.fillStyle = accentColor;
      const nb = 6;
      for (let i = 0; i < nb; i++) {
        const x = center - bandW / 2 + (bandW / nb) * i;
        const wob = live ? Math.sin(t * 5 + i) * 0.06 : 0;
        const v = peakH * (0.85 + wob);
        ctx.fillRect(x, h - v, bandW / nb - 1, v);
      }

      // tick label under narrow band
      ctx.fillStyle = fgColor;
      ctx.font = "11px JetBrains Mono, monospace";
      ctx.textAlign = "center";
      ctx.fillText("200 kHz", center, h - 6);
      ctx.textAlign = "left";
      ctx.fillStyle = lineColor;
      ctx.fillText("LTE", 8, h - 6);
      ctx.textAlign = "right";
      ctx.fillText("LTE", width - 8, h - 6);
      ctx.textAlign = "left";

      if (live) rafRef.current = requestAnimationFrame(draw);
    };
    rafRef.current = requestAnimationFrame(draw);
    return () => {
      cancelAnimationFrame(rafRef.current);
      ro.disconnect();
    };
  }, [live, accent]);

  return (
    <canvas
      ref={ref}
      style={{ width: "100%", height, display: "block" }}
      aria-hidden="true"
    />
  );
}

// Slow, faint pulse that radiates outward — for the hero background.
function PulseRings() {
  return (
    <svg
      className="pulse-rings"
      viewBox="0 0 800 800"
      preserveAspectRatio="xMidYMid slice"
      aria-hidden="true"
    >
      <defs>
        <radialGradient id="ring-grad" cx="50%" cy="50%" r="50%">
          <stop offset="0%" stopColor="var(--accent)" stopOpacity="0" />
          <stop offset="70%" stopColor="var(--accent)" stopOpacity="0.4" />
          <stop offset="100%" stopColor="var(--accent)" stopOpacity="0" />
        </radialGradient>
      </defs>
      {[0, 1, 2, 3].map(i => (
        <circle
          key={i}
          cx="400" cy="400"
          r="60"
          fill="none"
          stroke="url(#ring-grad)"
          strokeWidth="1"
          style={{
            transformOrigin: "400px 400px",
            animation: `pulse-ring 6s ${i * 1.5}s ease-out infinite`
          }}
        />
      ))}
      <style>{`
        @keyframes pulse-ring {
          0%   { transform: scale(0.4); opacity: 0; }
          15%  { opacity: 0.7; }
          100% { transform: scale(6); opacity: 0; }
        }
      `}</style>
    </svg>
  );
}

// Tiny live ticker — gives the page a "bid is active" feel.
function LiveTicker() {
  const [t, setT] = useState(() => new Date());
  useEffect(() => {
    const id = setInterval(() => setT(new Date()), 1000);
    return () => clearInterval(id);
  }, []);
  const utc = t.toISOString().replace("T", " ").slice(0, 19) + " UTC";
  return <span className="mono">{utc}</span>;
}

window.Spectrum = Spectrum;
window.PulseRings = PulseRings;
window.LiveTicker = LiveTicker;
