// Cosmos: starfield con parallax + un fotón ocasional + órbita estática.
// Un único componente <Cosmos /> que monta su propio canvas.

const { useEffect, useRef } = React;

function Cosmos({ density = 1, phosphor = "#7CFFB2", showOrbit = true, photonRate = 0.18 }) {
  const canvasRef = useRef(null);
  const stateRef = useRef({ stars: [], photons: [], orbit: null, t0: performance.now() });
  const propsRef = useRef({ density, phosphor, showOrbit, photonRate });
  propsRef.current = { density, phosphor, showOrbit, photonRate };

  useEffect(() => {
    const canvas = canvasRef.current;
    const ctx = canvas.getContext("2d");
    let raf;
    let dpr = Math.min(window.devicePixelRatio || 1, 2);
    let W, H;

    const resize = () => {
      W = canvas.clientWidth;
      H = canvas.clientHeight;
      canvas.width = W * dpr;
      canvas.height = H * dpr;
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
      buildStars();
    };

    const buildStars = () => {
      const d = propsRef.current.density;
      const n = Math.floor(W * H * 0.00018 * d);
      const stars = [];
      for (let i = 0; i < n; i++) {
        stars.push({
          x: Math.random() * W,
          y: Math.random() * H,
          z: Math.random() * 1 + 0.2, // depth (parallax)
          r: Math.random() * 1.1 + 0.2,
          tw: Math.random() * Math.PI * 2,
          twS: 0.4 + Math.random() * 1.6,
        });
      }
      stateRef.current.stars = stars;
      stateRef.current.orbit = {
        cx: W * 0.78,
        cy: H * 0.32,
        r: Math.min(W, H) * 0.18,
      };
    };

    const spawnPhoton = () => {
      // cruza la pantalla en una línea recta lentamente
      const fromTop = Math.random() < 0.5;
      const angle = (-30 + Math.random() * 60) * Math.PI / 180;
      const dir = Math.random() < 0.5 ? 1 : -1;
      const x = dir > 0 ? -40 : W + 40;
      const y = Math.random() * H;
      stateRef.current.photons.push({
        x, y,
        vx: dir * (60 + Math.random() * 40), // px/s
        vy: Math.tan(angle) * 8,
        life: 0,
        maxLife: 6 + Math.random() * 4,
        bright: 0.6 + Math.random() * 0.4,
      });
    };

    let lastT = performance.now();
    let photonAccum = 0;

    const frame = (now) => {
      const dt = Math.min(0.05, (now - lastT) / 1000);
      lastT = now;
      const t = (now - stateRef.current.t0) / 1000;
      const { phosphor, showOrbit, photonRate } = propsRef.current;

      // limpiar
      ctx.clearRect(0, 0, W, H);

      // estrellas con parallax sutil + twinkle
      const stars = stateRef.current.stars;
      const px = (Math.sin(t * 0.04) * 8);
      const py = (Math.cos(t * 0.03) * 5);
      for (let i = 0; i < stars.length; i++) {
        const s = stars[i];
        const tw = 0.55 + 0.45 * Math.sin(s.tw + t * s.twS);
        const r = s.r * (0.6 + 0.4 * tw);
        const a = (0.25 + 0.55 * tw) * (0.4 + s.z * 0.6);
        ctx.beginPath();
        ctx.fillStyle = `rgba(220,255,235,${a})`;
        ctx.arc(s.x + px * s.z, s.y + py * s.z, r, 0, Math.PI * 2);
        ctx.fill();
      }

      // órbita decorativa: circunferencia muy fina con un punto recorriéndola
      if (showOrbit && stateRef.current.orbit) {
        const o = stateRef.current.orbit;
        ctx.save();
        ctx.strokeStyle = hexToRgba(phosphor, 0.10);
        ctx.lineWidth = 0.6;
        ctx.beginPath();
        ctx.arc(o.cx, o.cy, o.r, 0, Math.PI * 2);
        ctx.stroke();

        // punto orbitando
        const a = t * 0.18;
        const ox = o.cx + Math.cos(a) * o.r;
        const oy = o.cy + Math.sin(a) * o.r;
        const grad = ctx.createRadialGradient(ox, oy, 0, ox, oy, 14);
        grad.addColorStop(0, hexToRgba(phosphor, 0.85));
        grad.addColorStop(1, hexToRgba(phosphor, 0));
        ctx.fillStyle = grad;
        ctx.beginPath();
        ctx.arc(ox, oy, 14, 0, Math.PI * 2);
        ctx.fill();
        ctx.fillStyle = phosphor;
        ctx.beginPath();
        ctx.arc(ox, oy, 1.6, 0, Math.PI * 2);
        ctx.fill();

        // un anillo más exterior
        ctx.strokeStyle = hexToRgba(phosphor, 0.05);
        ctx.beginPath();
        ctx.arc(o.cx, o.cy, o.r * 1.6, 0, Math.PI * 2);
        ctx.stroke();
        ctx.restore();
      }

      // fotones (poco frecuentes)
      photonAccum += dt;
      const interval = photonRate > 0 ? (1 / photonRate) : Infinity;
      if (photonAccum > interval) {
        photonAccum = 0;
        spawnPhoton();
      }
      const photons = stateRef.current.photons;
      for (let i = photons.length - 1; i >= 0; i--) {
        const p = photons[i];
        p.life += dt;
        p.x += p.vx * dt;
        p.y += p.vy * dt;
        const lifeFrac = p.life / p.maxLife;
        if (p.life > p.maxLife || p.x < -80 || p.x > W + 80) {
          photons.splice(i, 1);
          continue;
        }
        const fade = Math.sin(Math.PI * lifeFrac); // entra y sale
        const alpha = fade * p.bright;
        // estela
        const tailLen = 80;
        const dx = -p.vx / Math.hypot(p.vx, p.vy) * tailLen;
        const dy = -p.vy / Math.hypot(p.vx, p.vy) * tailLen;
        const tail = ctx.createLinearGradient(p.x, p.y, p.x + dx, p.y + dy);
        tail.addColorStop(0, hexToRgba(phosphor, alpha * 0.9));
        tail.addColorStop(1, hexToRgba(phosphor, 0));
        ctx.strokeStyle = tail;
        ctx.lineWidth = 1.4;
        ctx.beginPath();
        ctx.moveTo(p.x, p.y);
        ctx.lineTo(p.x + dx, p.y + dy);
        ctx.stroke();
        // núcleo
        const grd = ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, 8);
        grd.addColorStop(0, hexToRgba(phosphor, alpha));
        grd.addColorStop(1, hexToRgba(phosphor, 0));
        ctx.fillStyle = grd;
        ctx.beginPath();
        ctx.arc(p.x, p.y, 8, 0, Math.PI * 2);
        ctx.fill();
      }

      raf = requestAnimationFrame(frame);
    };

    resize();
    window.addEventListener("resize", resize);
    raf = requestAnimationFrame(frame);
    return () => {
      cancelAnimationFrame(raf);
      window.removeEventListener("resize", resize);
    };
  }, []);

  return <canvas ref={canvasRef} className="cosmos" />;
}

function hexToRgba(hex, a) {
  const h = hex.replace("#", "");
  const r = parseInt(h.slice(0, 2), 16);
  const g = parseInt(h.slice(2, 4), 16);
  const b = parseInt(h.slice(4, 6), 16);
  return `rgba(${r},${g},${b},${a})`;
}

window.Cosmos = Cosmos;
window.hexToRgba = hexToRgba;
