import { useRef, useEffect, useCallback } from 'react';

/**
 * Aurora background — 5 large diffuse orbs with additive blending.
 * Orbs are deliberately offset from center to avoid uniform "blue blob" look.
 * Mouse gently pushes nearby orbs (10-20px, very subtle).
 */

interface Orb {
  cx: number;   // base center X ratio (0-1)
  cy: number;   // base center Y ratio (0-1)
  color: [number, number, number];
  alpha: number; // peak alpha — varies per orb for brightness contrast
  phase: number;
  freqX: number;
  freqY: number;
  ampX: number;
  ampY: number;
  radius: number; // ratio of max(w,h)
  // breathing
  breathFreq: number;
  breathAmp: number;
}

// Orbs deliberately NOT centered — some in corners, some offset,
// creating uneven light distribution with dark pockets.
const ORBS: Orb[] = [
  // Cyan — upper-left area, large and bright
  { cx: 0.25, cy: 0.30, color: [126, 220, 200], alpha: 0.28,
    phase: 0, freqX: 0.00012, freqY: 0.00010, ampX: 0.12, ampY: 0.10,
    radius: 0.50, breathFreq: 0.0004, breathAmp: 0.06 },
  // Purple — lower-right, medium
  { cx: 0.72, cy: 0.65, color: [108, 99, 255], alpha: 0.22,
    phase: 1.8, freqX: 0.00010, freqY: 0.00014, ampX: 0.14, ampY: 0.12,
    radius: 0.45, breathFreq: 0.0003, breathAmp: 0.08 },
  // Blue — center-right, smaller and dimmer (fills gap)
  { cx: 0.58, cy: 0.38, color: [59, 130, 246], alpha: 0.18,
    phase: 3.2, freqX: 0.00015, freqY: 0.00008, ampX: 0.10, ampY: 0.15,
    radius: 0.38, breathFreq: 0.0005, breathAmp: 0.07 },
  // Light purple — bottom-left corner, dim accent
  { cx: 0.20, cy: 0.70, color: [167, 139, 250], alpha: 0.15,
    phase: 4.5, freqX: 0.00008, freqY: 0.00012, ampX: 0.16, ampY: 0.08,
    radius: 0.40, breathFreq: 0.00035, breathAmp: 0.10 },
  // Bright cyan — upper-right, small bright accent
  { cx: 0.78, cy: 0.25, color: [34, 211, 238], alpha: 0.20,
    phase: 5.8, freqX: 0.00014, freqY: 0.00016, ampX: 0.08, ampY: 0.12,
    radius: 0.35, breathFreq: 0.00045, breathAmp: 0.09 },
];

// Mouse influence radius (px) and max push distance (px)
const MOUSE_RADIUS = 400;
const MOUSE_PUSH = 28;

export function AuroraCanvas() {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const grainRef = useRef<HTMLCanvasElement>(null);
  const mouseRef = useRef({ x: -9999, y: -9999, active: false });

  const handleMouseMove = useCallback((e: MouseEvent) => {
    mouseRef.current.x = e.clientX;
    mouseRef.current.y = e.clientY;
    mouseRef.current.active = true;
  }, []);

  const handleMouseLeave = useCallback(() => {
    mouseRef.current.active = false;
  }, []);

  // ── Aurora animation ──
  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    if (!ctx) return;

    let w = window.innerWidth;
    let h = window.innerHeight;

    function resize() {
      w = window.innerWidth;
      h = window.innerHeight;
      const dpr = w < 768 ? 0.5 : Math.min(window.devicePixelRatio, 1.5);
      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();

    let animId: number;
    const t0 = performance.now();
    // Smoothed mouse position for gentle push
    let smoothMx = -9999;
    let smoothMy = -9999;

    function draw(now: number) {
      const t = now - t0;
      ctx!.clearRect(0, 0, w, h);
      ctx!.globalCompositeOperation = 'lighter';

      // Smooth mouse tracking (lerp toward actual position)
      const mouse = mouseRef.current;
      if (mouse.active) {
        smoothMx += (mouse.x - smoothMx) * 0.035;
        smoothMy += (mouse.y - smoothMy) * 0.035;
      } else {
        // Slowly drift smoothed mouse away (return to no-influence)
        smoothMx += (-9999 - smoothMx) * 0.01;
        smoothMy += (-9999 - smoothMy) * 0.01;
      }

      for (const orb of ORBS) {
        // Base position from slow sinusoidal movement
        let x = w * (orb.cx + Math.sin(t * orb.freqX + orb.phase) * orb.ampX);
        let y = h * (orb.cy + Math.cos(t * orb.freqY + orb.phase * 0.7) * orb.ampY);

        // Mouse push — gently offset orb away from cursor
        const dx = x - smoothMx;
        const dy = y - smoothMy;
        const dist = Math.sqrt(dx * dx + dy * dy);
        if (dist < MOUSE_RADIUS && dist > 1) {
          const strength = (1 - dist / MOUSE_RADIUS) * MOUSE_PUSH;
          x += (dx / dist) * strength;
          y += (dy / dist) * strength;
        }

        // Breathing: radius and alpha pulse slowly
        const breathT = Math.sin(t * orb.breathFreq + orb.phase * 1.3);
        const r = Math.max(w, h) * orb.radius * (1 + breathT * orb.breathAmp);
        const a = orb.alpha * (1 + breathT * 0.15);

        const [cr, cg, cb] = orb.color;
        const grad = ctx!.createRadialGradient(x, y, 0, x, y, r);
        grad.addColorStop(0,   `rgba(${cr},${cg},${cb},${(a).toFixed(3)})`);
        grad.addColorStop(0.25, `rgba(${cr},${cg},${cb},${(a * 0.5).toFixed(3)})`);
        grad.addColorStop(0.5, `rgba(${cr},${cg},${cb},${(a * 0.15).toFixed(3)})`);
        grad.addColorStop(0.8, `rgba(${cr},${cg},${cb},${(a * 0.03).toFixed(3)})`);
        grad.addColorStop(1,   `rgba(${cr},${cg},${cb},0)`);

        ctx!.fillStyle = grad;
        ctx!.beginPath();
        ctx!.arc(x, y, r, 0, Math.PI * 2);
        ctx!.fill();
      }

      ctx!.globalCompositeOperation = 'source-over';
      animId = requestAnimationFrame(draw);
    }

    animId = requestAnimationFrame(draw);
    window.addEventListener('resize', resize);
    window.addEventListener('mousemove', handleMouseMove, { passive: true });
    document.addEventListener('mouseleave', handleMouseLeave);

    return () => {
      cancelAnimationFrame(animId);
      window.removeEventListener('resize', resize);
      window.removeEventListener('mousemove', handleMouseMove);
      document.removeEventListener('mouseleave', handleMouseLeave);
    };
  }, [handleMouseMove, handleMouseLeave]);

  // ── Film grain — 4 FPS low-noise ──
  useEffect(() => {
    const canvas = grainRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    if (!ctx) return;

    canvas.width = 256;
    canvas.height = 256;

    let animId: number;
    let lastFrame = 0;

    function drawGrain(now: number) {
      if (now - lastFrame > 250) {
        lastFrame = now;
        const img = ctx!.createImageData(256, 256);
        const d = img.data;
        for (let i = 0; i < d.length; i += 4) {
          const v = Math.random() * 255;
          d[i] = d[i + 1] = d[i + 2] = v;
          d[i + 3] = 255;
        }
        ctx!.putImageData(img, 0, 0);
      }
      animId = requestAnimationFrame(drawGrain);
    }

    animId = requestAnimationFrame(drawGrain);
    return () => cancelAnimationFrame(animId);
  }, []);

  return (
    <>
      {/* Layer 1: Vignette — radial darkening, heavy at edges */}
      <div
        style={{
          position: 'absolute',
          inset: 0,
          zIndex: 1,
          background: 'radial-gradient(ellipse 65% 55% at 50% 50%, transparent 0%, rgba(0,0,0,0.8) 100%)',
          pointerEvents: 'none',
        }}
      />

      {/* Layer 2: Film grain */}
      <canvas
        ref={grainRef}
        style={{
          position: 'absolute',
          inset: 0,
          zIndex: 2,
          width: '100%',
          height: '100%',
          opacity: 0.035,
          pointerEvents: 'none',
          mixBlendMode: 'overlay',
        }}
      />

      {/* Layer 3: Aurora — blur merges orbs into organic glow */}
      <canvas
        ref={canvasRef}
        style={{
          position: 'absolute',
          inset: 0,
          zIndex: 3,
          filter: 'blur(50px)',
          pointerEvents: 'none',
        }}
      />

      {/* Layer 4: Top/bottom gradient mask */}
      <div
        style={{
          position: 'absolute',
          inset: 0,
          zIndex: 4,
          pointerEvents: 'none',
          background:
            'linear-gradient(to bottom, rgba(0,0,0,0.5) 0%, transparent 18%, transparent 82%, rgba(0,0,0,0.5) 100%)',
        }}
      />
    </>
  );
}
