// Realistic neon wireframe globe — canvas, no deps
function NeonGlobe({ size = 880 }) {
  const canvasRef = React.useRef(null);

  React.useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const dpr = Math.min(window.devicePixelRatio || 1, 2);
    canvas.width = size * dpr;
    canvas.height = size * dpr;
    const ctx = canvas.getContext('2d');
    ctx.scale(dpr, dpr);

    const cx = size / 2, cy = size / 2;
    const R = size * 0.40;

    // Continent dots — abstract noise mask, denser & more landlike
    const continents = [];
    const seed = (a, b) => {
      const x = Math.sin(a * 12.9898 + b * 78.233) * 43758.5453;
      return x - Math.floor(x);
    };
    const fbm = (lat, lon) => {
      let v = 0, a = 0.5, f = 1;
      for (let i = 0; i < 4; i++) {
        v += a * seed(Math.round(lat * f * 6) + i, Math.round(lon * f * 6) - i);
        a *= 0.55; f *= 2;
      }
      return v;
    };
    const latSteps = 90;
    for (let i = 0; i <= latSteps; i++) {
      const lat = -Math.PI / 2 + (i / latSteps) * Math.PI;
      const cosLat = Math.cos(lat);
      const count = Math.max(8, Math.round(180 * cosLat));
      for (let j = 0; j < count; j++) {
        const lon = (j / count) * Math.PI * 2;
        const n = fbm(lat, lon);
        // landmass threshold; bias towards mid-latitudes
        const polar = 1 - Math.pow(Math.abs(lat) / (Math.PI / 2), 2.4);
        if (n * polar > 0.42 && Math.abs(lat) < 1.4) {
          continents.push({ lat, lon, weight: (n * polar - 0.42) * 3 });
        }
      }
    }

    // Hot trade routes — animated arcs between random points
    const cities = [];
    for (let i = 0; i < 14; i++) {
      cities.push({
        lat: (Math.random() - 0.5) * 1.6,
        lon: Math.random() * Math.PI * 2,
      });
    }
    const arcs = [];
    for (let i = 0; i < 10; i++) {
      const a = cities[Math.floor(Math.random() * cities.length)];
      const b = cities[Math.floor(Math.random() * cities.length)];
      if (a !== b) arcs.push({ a, b, t0: Math.random(), speed: 0.0008 + Math.random() * 0.0014 });
    }

    let rot = 0;
    let tilt = 0.18;
    let dragRot = 0, dragTilt = 0;
    let dragging = false;
    let lastX = 0, lastY = 0;
    let velX = 0, velY = 0;
    let autoSpin = true;
    let autoTimer;

    canvas.style.pointerEvents = 'auto';
    canvas.style.cursor = 'grab';

    const onDown = (e) => {
      dragging = true;
      autoSpin = false;
      clearTimeout(autoTimer);
      const p = e.touches ? e.touches[0] : e;
      lastX = p.clientX; lastY = p.clientY;
      canvas.style.cursor = 'grabbing';
      e.preventDefault();
    };
    const onMove = (e) => {
      if (!dragging) return;
      const p = e.touches ? e.touches[0] : e;
      const dx = p.clientX - lastX;
      const dy = p.clientY - lastY;
      velX = dx * 0.005;
      velY = dy * 0.005;
      dragRot += velX;
      dragTilt = Math.max(-1.2, Math.min(1.2, dragTilt + velY));
      lastX = p.clientX; lastY = p.clientY;
      e.preventDefault();
    };
    const onUp = () => {
      if (!dragging) return;
      dragging = false;
      canvas.style.cursor = 'grab';
      autoTimer = setTimeout(() => { autoSpin = true; }, 2400);
    };
    canvas.addEventListener('mousedown', onDown);
    window.addEventListener('mousemove', onMove);
    window.addEventListener('mouseup', onUp);
    canvas.addEventListener('touchstart', onDown, { passive: false });
    canvas.addEventListener('touchmove', onMove, { passive: false });
    canvas.addEventListener('touchend', onUp);

    let raf;
    const accentVal = () => getComputedStyle(document.documentElement).getPropertyValue('--accent').trim() || '#7C5CFF';
    const accentGlow = () => getComputedStyle(document.documentElement).getPropertyValue('--accent-glow').trim() || 'rgba(124,92,255,0.35)';

    const project = (lat, lon, rotation) => {
      const lon2 = lon + rotation;
      const x0 = Math.cos(lat) * Math.sin(lon2);
      const y0 = Math.sin(lat);
      const z0 = Math.cos(lat) * Math.cos(lon2);
      // tilt around X axis
      const cosT = Math.cos(tilt), sinT = Math.sin(tilt);
      const y = y0 * cosT - z0 * sinT;
      const z = y0 * sinT + z0 * cosT;
      const x = x0;
      return { x: cx + x * R, y: cy - y * R, z };
    };

    const drawArc = (a, b, t, accent) => {
      // sample along great circle (slerp)
      const toVec = (lat, lon) => {
        const lon2 = lon + rot;
        const x0 = Math.cos(lat) * Math.sin(lon2);
        const y0 = Math.sin(lat);
        const z0 = Math.cos(lat) * Math.cos(lon2);
        const cosT = Math.cos(tilt), sinT = Math.sin(tilt);
        return {
          x: x0,
          y: y0 * cosT - z0 * sinT,
          z: y0 * sinT + z0 * cosT,
        };
      };
      const v1 = toVec(a.lat, a.lon);
      const v2 = toVec(b.lat, b.lon);
      const dot = Math.max(-1, Math.min(1, v1.x*v2.x + v1.y*v2.y + v1.z*v2.z));
      const omega = Math.acos(dot);
      if (omega < 0.01) return;
      const so = Math.sin(omega);
      const segs = 60;
      const trail = 0.22;
      for (let i = 0; i < segs; i++) {
        const u = i / segs;
        const dist = ((u - t) + 1) % 1;
        if (dist > trail) continue;
        const alpha = (1 - dist / trail);
        const s1 = Math.sin((1 - u) * omega) / so;
        const s2 = Math.sin(u * omega) / so;
        const px = v1.x * s1 + v2.x * s2;
        const py = v1.y * s1 + v2.y * s2;
        const pz = v1.z * s1 + v2.z * s2;
        // bulge outward slightly (great-circle flat on sphere; render at R*1.02 for hover)
        const bulge = 1 + 0.04 * Math.sin(u * Math.PI);
        const sx = cx + px * R * bulge;
        const sy = cy - py * R * bulge;
        if (pz > 0) {
          ctx.fillStyle = accent;
          ctx.globalAlpha = alpha * 0.9;
          ctx.beginPath(); ctx.arc(sx, sy, 1.6, 0, Math.PI * 2); ctx.fill();
          ctx.globalAlpha = alpha * 0.25;
          ctx.beginPath(); ctx.arc(sx, sy, 4, 0, Math.PI * 2); ctx.fill();
        }
      }
      ctx.globalAlpha = 1;
    };

    const draw = () => {
      ctx.clearRect(0, 0, size, size);
      const a = accentVal();
      const ag = accentGlow();

      // Outer atmosphere glow
      const gr = ctx.createRadialGradient(cx, cy, R * 0.95, cx, cy, R * 1.55);
      gr.addColorStop(0, ag);
      gr.addColorStop(0.5, 'rgba(124,92,255,0.06)');
      gr.addColorStop(1, 'rgba(0,0,0,0)');
      ctx.fillStyle = gr;
      ctx.beginPath(); ctx.arc(cx, cy, R * 1.55, 0, Math.PI * 2); ctx.fill();

      // Sphere body — radial gradient with terminator
      const body = ctx.createRadialGradient(cx - R * 0.25, cy - R * 0.3, R * 0.1, cx, cy, R);
      body.addColorStop(0, 'rgba(28, 22, 50, 1)');
      body.addColorStop(0.55, 'rgba(14, 12, 26, 1)');
      body.addColorStop(1, 'rgba(6, 6, 12, 1)');
      ctx.fillStyle = body;
      ctx.beginPath(); ctx.arc(cx, cy, R, 0, Math.PI * 2); ctx.fill();

      // Inner terminator shadow (right side)
      ctx.save();
      ctx.beginPath(); ctx.arc(cx, cy, R, 0, Math.PI * 2); ctx.clip();
      const term = ctx.createRadialGradient(cx + R * 0.55, cy + R * 0.2, R * 0.1, cx + R * 0.6, cy + R * 0.2, R * 1.2);
      term.addColorStop(0, 'rgba(0,0,0,0)');
      term.addColorStop(1, 'rgba(0,0,0,0.85)');
      ctx.fillStyle = term;
      ctx.fillRect(cx - R, cy - R, R * 2, R * 2);
      ctx.restore();

      // Lat lines
      ctx.lineWidth = 0.5;
      const latLines = 18;
      for (let i = 1; i < latLines; i++) {
        const lat = -Math.PI / 2 + (i / latLines) * Math.PI;
        ctx.beginPath();
        let started = false;
        for (let j = 0; j <= 160; j++) {
          const lon = (j / 160) * Math.PI * 2;
          const p = project(lat, lon, rot);
          if (p.z > 0) {
            const alpha = Math.min(1, p.z * 1.4) * 0.13;
            ctx.strokeStyle = `rgba(255,255,255,${alpha})`;
            if (!started) { ctx.moveTo(p.x, p.y); started = true; }
            else ctx.lineTo(p.x, p.y);
          } else if (started) { ctx.stroke(); ctx.beginPath(); started = false; }
        }
        if (started) ctx.stroke();
      }

      // Lon lines
      const lonLines = 24;
      for (let j = 0; j < lonLines; j++) {
        const lon = (j / lonLines) * Math.PI * 2;
        ctx.beginPath();
        let started = false;
        for (let i = 0; i <= 160; i++) {
          const lat = -Math.PI / 2 + (i / 160) * Math.PI;
          const p = project(lat, lon, rot);
          if (p.z > 0) {
            const alpha = Math.min(1, p.z * 1.4) * 0.10;
            ctx.strokeStyle = `rgba(255,255,255,${alpha})`;
            if (!started) { ctx.moveTo(p.x, p.y); started = true; }
            else ctx.lineTo(p.x, p.y);
          } else if (started) { ctx.stroke(); ctx.beginPath(); started = false; }
        }
        if (started) ctx.stroke();
      }

      // Continent dots
      for (const pt of continents) {
        const p = project(pt.lat, pt.lon, rot);
        if (p.z > 0.05) {
          const lit = Math.max(0, 1 - (p.x - cx + R * 0.1) / (R * 1.4)); // brighter on left lit side
          const alpha = Math.min(1, p.z * 1.4) * (0.55 + lit * 0.45);
          ctx.fillStyle = a;
          ctx.globalAlpha = alpha;
          const r = 1.1 + p.z * 1.4 * Math.min(1, pt.weight);
          ctx.beginPath(); ctx.arc(p.x, p.y, r, 0, Math.PI * 2); ctx.fill();
        }
      }
      ctx.globalAlpha = 1;

      // Trade-route arcs (animated)
      arcs.forEach(arc => {
        arc.t0 = (arc.t0 + arc.speed) % 1;
        drawArc(arc.a, arc.b, arc.t0, a);
      });

      // City pulse markers
      cities.forEach((c, i) => {
        const p = project(c.lat, c.lon, rot);
        if (p.z > 0.1) {
          const pulse = (Math.sin(performance.now() * 0.002 + i) + 1) / 2;
          ctx.fillStyle = a;
          ctx.globalAlpha = 0.9;
          ctx.beginPath(); ctx.arc(p.x, p.y, 2.2, 0, Math.PI * 2); ctx.fill();
          ctx.globalAlpha = 0.35 * (1 - pulse);
          ctx.beginPath(); ctx.arc(p.x, p.y, 2 + pulse * 14, 0, Math.PI * 2); ctx.fill();
        }
      });
      ctx.globalAlpha = 1;

      // Equator highlight
      ctx.strokeStyle = a;
      ctx.lineWidth = 0.8;
      ctx.beginPath();
      let s = false;
      for (let j = 0; j <= 220; j++) {
        const lon = (j / 220) * Math.PI * 2;
        const p = project(0, lon, rot);
        if (p.z > 0) {
          ctx.globalAlpha = 0.18 + p.z * 0.35;
          if (!s) { ctx.moveTo(p.x, p.y); s = true; }
          else ctx.lineTo(p.x, p.y);
        } else if (s) { ctx.stroke(); ctx.beginPath(); s = false; }
      }
      if (s) ctx.stroke();
      ctx.globalAlpha = 1;

      // Outer ring + ticks
      ctx.strokeStyle = a;
      ctx.lineWidth = 1;
      ctx.globalAlpha = 0.45;
      ctx.beginPath(); ctx.arc(cx, cy, R, 0, Math.PI * 2); ctx.stroke();
      ctx.globalAlpha = 0.12;
      ctx.beginPath(); ctx.arc(cx, cy, R * 1.06, 0, Math.PI * 2); ctx.stroke();
      ctx.globalAlpha = 0.06;
      ctx.beginPath(); ctx.arc(cx, cy, R * 1.18, 0, Math.PI * 2); ctx.stroke();

      // Tick marks around outer ring
      for (let k = 0; k < 60; k++) {
        const ang = (k / 60) * Math.PI * 2;
        const r1 = R * 1.06;
        const r2 = k % 5 === 0 ? R * 1.10 : R * 1.075;
        ctx.globalAlpha = k % 5 === 0 ? 0.4 : 0.18;
        ctx.beginPath();
        ctx.moveTo(cx + Math.cos(ang) * r1, cy + Math.sin(ang) * r1);
        ctx.lineTo(cx + Math.cos(ang) * r2, cy + Math.sin(ang) * r2);
        ctx.stroke();
      }
      ctx.globalAlpha = 1;

      if (autoSpin) rot += 0.0014;
      rot += dragRot;
      dragRot *= 0.0;
      if (!dragging) {
        velX *= 0.92;
        if (Math.abs(velX) > 0.0001) rot += velX;
      }
      raf = requestAnimationFrame(draw);
    };

    raf = requestAnimationFrame(draw);
    return () => {
      cancelAnimationFrame(raf);
      canvas.removeEventListener('mousedown', onDown);
      window.removeEventListener('mousemove', onMove);
      window.removeEventListener('mouseup', onUp);
      canvas.removeEventListener('touchstart', onDown);
      canvas.removeEventListener('touchmove', onMove);
      canvas.removeEventListener('touchend', onUp);
      clearTimeout(autoTimer);
    };
  }, [size]);

  return (
    <div className="globe-wrap">
      <canvas ref={canvasRef} style={{ width: size, height: size }} />
      <div className="globe-hud" aria-hidden="true">
        <div className="hud-tl mono">
          <div>LAT  01°22'N</div>
          <div>LON 103°48'E</div>
          <div className="dim">SINGAPORE — 074</div>
        </div>
        <div className="hud-br mono">
          <div className="dim">NODE / 074</div>
          <div>SYNC ●</div>
          <div>UPLINK · STABLE</div>
        </div>
        <div className="hud-hint mono">DRAG TO ROTATE</div>
      </div>
    </div>
  );
}

window.NeonGlobe = NeonGlobe;
