/* ============================================================
   AmbientGlobe — subtle dotted sphere for the homepage.
   Auto-rotates slowly; gentle cursor influence; glowing
   office pins + faint follow-the-sun arcs.
   Used behind the hero (large, dim) and in the offices band.
   ============================================================ */

const HOME_OFFICES = [
  { code: "DXB", city: "Dubai",    lat: 25.2048, lng: 55.2708, hq: true },
  { code: "DAM", city: "Damascus", lat: 33.5138, lng: 36.2765 },
  { code: "IST", city: "Istanbul", lat: 41.0082, lng: 28.9784 },
  { code: "TLL", city: "Tallinn",  lat: 59.4370, lng: 24.7536 },
];

function AmbientGlobe({
  size = 560,
  dotColor = "rgba(150,140,210,0.9)",
  pinColor = "#9a7bff",
  arcColor = "#8a6bff",
  coreColor = "#0c0e1a",
  showLabels = false,
  cursorInfluence = 0.0,
  spin = 0.00012,
  className = "",
}) {
  const canvasRef = React.useRef(null);
  const wrapRef = React.useRef(null);
  const rafRef = React.useRef(null);
  const rotRef = React.useRef(0.4);
  const tRef = React.useRef(0);
  const targetTiltRef = React.useRef(0);
  const tiltRef = React.useRef(0);
  const targetYawRef = React.useRef(0);
  const yawRef = React.useRef(0);

  React.useEffect(() => {
    const canvas = canvasRef.current;
    const wrap = wrapRef.current;
    if (!canvas || !wrap) return;
    const ctx = canvas.getContext("2d");
    const data = window.WORLD_MAP;
    if (!data) return;

    const sphereDots = data.dots.map(([px, py]) => {
      const lng = (px / data.width) * 360 - 180;
      const lat = 90 - (py / data.height) * 180;
      const phi = (lat * Math.PI) / 180;
      const lam = (lng * Math.PI) / 180;
      return {
        x: Math.cos(phi) * Math.cos(lam),
        y: Math.sin(phi),
        z: Math.cos(phi) * Math.sin(lam),
      };
    });

    const officePts = HOME_OFFICES.map((o) => {
      const phi = (o.lat * Math.PI) / 180;
      const lam = (o.lng * Math.PI) / 180;
      return {
        ...o,
        v: {
          x: Math.cos(phi) * Math.cos(lam),
          y: Math.sin(phi),
          z: Math.cos(phi) * Math.sin(lam),
        },
      };
    });

    let W = 0, H = 0;
    const dpr = Math.min(window.devicePixelRatio || 1, 2);
    const resize = () => {
      const r = wrap.getBoundingClientRect();
      W = Math.floor(r.width);
      H = Math.floor(r.height);
      canvas.width = W * dpr;
      canvas.height = H * dpr;
      canvas.style.width = W + "px";
      canvas.style.height = H + "px";
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
    };
    resize();
    window.addEventListener("resize", resize);

    let onPointer = null;
    if (cursorInfluence > 0) {
      onPointer = (e) => {
        const cx = window.innerWidth / 2;
        const cy = window.innerHeight / 2;
        targetYawRef.current = ((e.clientX - cx) / cx) * cursorInfluence;
        targetTiltRef.current = ((e.clientY - cy) / cy) * cursorInfluence * 0.6;
      };
      window.addEventListener("pointermove", onPointer, { passive: true });
    }

    let visible = true;
    const io = new IntersectionObserver(
      (entries) => { visible = entries[0].isIntersecting; },
      { threshold: 0 }
    );
    io.observe(wrap);

    let lastT = performance.now();
    const draw = (now) => {
      const dt = now - lastT;
      lastT = now;
      rotRef.current += dt * spin;
      tRef.current += dt;
      yawRef.current += (targetYawRef.current - yawRef.current) * 0.06;
      tiltRef.current += (targetTiltRef.current - tiltRef.current) * 0.06;

      if (!visible) { rafRef.current = requestAnimationFrame(draw); return; }

      ctx.clearRect(0, 0, W, H);
      const cx = W / 2;
      const cy = H / 2;
      const R = Math.min(W, H) * 0.42;
      const rot = rotRef.current + yawRef.current;
      const tilt = tiltRef.current;
      const sinR = Math.sin(rot), cosR = Math.cos(rot);
      const sinT = Math.sin(tilt), cosT = Math.cos(tilt);

      // core sphere shading
      const grad = ctx.createRadialGradient(cx - R * 0.32, cy - R * 0.34, R * 0.1, cx, cy, R);
      grad.addColorStop(0, coreColor + "ff");
      grad.addColorStop(0.72, coreColor + "cc");
      grad.addColorStop(1, coreColor + "00");
      ctx.fillStyle = grad;
      ctx.beginPath();
      ctx.arc(cx, cy, R, 0, Math.PI * 2);
      ctx.fill();

      const project = (v) => {
        // rotate around Y (rot), then X (tilt)
        let x = v.x * cosR + v.z * sinR;
        let z = -v.x * sinR + v.z * cosR;
        let y = v.y;
        const y2 = y * cosT - z * sinT;
        const z2 = y * sinT + z * cosT;
        return { sx: cx + x * R, sy: cy - y2 * R, z: z2 };
      };

      // continent dots
      ctx.fillStyle = dotColor;
      for (let i = 0; i < sphereDots.length; i++) {
        const p = project(sphereDots[i]);
        if (p.z < 0.04) continue;
        ctx.globalAlpha = 0.18 + p.z * 0.72;
        ctx.beginPath();
        ctx.arc(p.sx, p.sy, 1.15, 0, Math.PI * 2);
        ctx.fill();
      }
      ctx.globalAlpha = 1;

      const projected = officePts.map((o) => {
        const p = project(o.v);
        return { ...o, ...p, front: p.z >= 0 };
      });

      // arcs between consecutive offices
      const phase = (tRef.current * 0.0004) % 1;
      const n = projected.length;
      for (let i = 0; i < n; i++) {
        const a = projected[i];
        const b = projected[(i + 1) % n];
        if (!a.front || !b.front) continue;
        const active = Math.floor(phase * n) === i;
        const dx = b.sx - a.sx, dy = b.sy - a.sy;
        const len = Math.hypot(dx, dy) || 1;
        const lift = Math.min(len * 0.32, R * 0.22);
        const nx = -dy / len, ny = dx / len;
        const mx = (a.sx + b.sx) / 2 + nx * lift;
        const my = (a.sy + b.sy) / 2 + ny * lift - Math.min(len * 0.08, 14);
        ctx.beginPath();
        ctx.moveTo(a.sx, a.sy);
        ctx.quadraticCurveTo(mx, my, b.sx, b.sy);
        ctx.strokeStyle = arcColor + (active ? "dd" : "44");
        ctx.lineWidth = active ? 1.5 : 0.9;
        ctx.shadowBlur = active ? 12 : 0;
        ctx.shadowColor = pinColor;
        ctx.stroke();
        ctx.shadowBlur = 0;
      }

      // office pins
      for (let i = 0; i < projected.length; i++) {
        const o = projected[i];
        if (!o.front) continue;
        const pulse = o.hq ? 1 : 0.6 + 0.4 * Math.abs(Math.sin(tRef.current * 0.002 + i));
        const rad = (o.hq ? 4.6 : 3) * (0.7 + 0.3 * pulse);
        ctx.shadowBlur = o.hq ? 20 : 10;
        ctx.shadowColor = pinColor;
        ctx.fillStyle = pinColor;
        ctx.globalAlpha = 0.5 + 0.5 * o.z;
        ctx.beginPath();
        ctx.arc(o.sx, o.sy, rad, 0, Math.PI * 2);
        ctx.fill();
        ctx.shadowBlur = 0;
        ctx.globalAlpha = 1;
        if (showLabels && o.z > 0.45) {
          ctx.fillStyle = "rgba(255,255,255,0.92)";
          ctx.font = "500 11px 'Geist Mono', ui-monospace, monospace";
          ctx.fillText(o.code, o.sx + 9, o.sy - 7);
        }
      }

      rafRef.current = requestAnimationFrame(draw);
    };
    rafRef.current = requestAnimationFrame(draw);

    return () => {
      cancelAnimationFrame(rafRef.current);
      window.removeEventListener("resize", resize);
      if (onPointer) window.removeEventListener("pointermove", onPointer);
      io.disconnect();
    };
  }, [dotColor, pinColor, arcColor, coreColor, showLabels, cursorInfluence, spin]);

  return (
    <div ref={wrapRef} className={`ambient-globe ${className}`} style={{ width: "100%", height: "100%" }}>
      <canvas ref={canvasRef} />
    </div>
  );
}

window.AmbientGlobe = AmbientGlobe;
window.HOME_OFFICES = HOME_OFFICES;
