// effects.jsx — Laser pointer, sound, konami, countUp

function LaserPointer() {
  const canvasRef = React.useRef(null);
  const dotRef = React.useRef(null);
  const strokesRef = React.useRef([]);
  const drawingRef = React.useRef(false);
  const currentRef = React.useRef([]);
  const rafRef = React.useRef(0);

  React.useEffect(() => {
    const canvas = canvasRef.current;
    const ctx = canvas.getContext('2d');

    const resize = () => {
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;
    };
    resize();
    window.addEventListener('resize', resize);

    const isInteractive = (el) => {
      if (!el || !el.closest) return false;
      return !!el.closest('button, a, input, select, textarea, [role="button"], .c-stk, .c-mute, form');
    };

    const onMove = (e) => {
      if (dotRef.current) {
        dotRef.current.style.left = (e.clientX - 5) + 'px';
        dotRef.current.style.top = (e.clientY - 5) + 'px';
        dotRef.current.style.opacity = '1';
      }
      if (drawingRef.current) {
        currentRef.current.push({ x: e.clientX, y: e.clientY });
      }
    };

    const onDown = (e) => {
      if (e.button !== 0) return;
      if (isInteractive(e.target)) return;
      drawingRef.current = true;
      currentRef.current = [{ x: e.clientX, y: e.clientY }];
      document.body.style.userSelect = 'none';
    };

    const onUp = () => {
      if (!drawingRef.current) return;
      drawingRef.current = false;
      document.body.style.userSelect = '';
      if (currentRef.current.length > 3) {
        strokesRef.current.push({
          points: [...currentRef.current],
          created: Date.now(),
        });
      }
      currentRef.current = [];
    };

    const onLeave = () => {
      if (dotRef.current) dotRef.current.style.opacity = '0';
    };

    const drawStroke = (points, alpha) => {
      if (points.length < 2) return;
      ctx.save();
      ctx.globalAlpha = alpha;

      ctx.shadowColor = 'rgba(255, 61, 0, 0.9)';
      ctx.shadowBlur = 20;
      ctx.strokeStyle = 'rgba(255, 61, 0, ' + alpha + ')';
      ctx.lineWidth = 3;
      ctx.lineCap = 'round';
      ctx.lineJoin = 'round';
      ctx.beginPath();
      ctx.moveTo(points[0].x, points[0].y);
      for (var i = 1; i < points.length; i++) {
        var xc = (points[i].x + points[i - 1].x) / 2;
        var yc = (points[i].y + points[i - 1].y) / 2;
        ctx.quadraticCurveTo(points[i - 1].x, points[i - 1].y, xc, yc);
      }
      ctx.stroke();

      ctx.shadowBlur = 0;
      ctx.strokeStyle = 'rgba(255, 220, 120, ' + (alpha * 0.7) + ')';
      ctx.lineWidth = 1.5;
      ctx.beginPath();
      ctx.moveTo(points[0].x, points[0].y);
      for (var i = 1; i < points.length; i++) {
        var xc = (points[i].x + points[i - 1].x) / 2;
        var yc = (points[i].y + points[i - 1].y) / 2;
        ctx.quadraticCurveTo(points[i - 1].x, points[i - 1].y, xc, yc);
      }
      ctx.stroke();
      ctx.restore();
    };

    const render = () => {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      var now = Date.now();
      var DURATION = 5000;

      strokesRef.current = strokesRef.current.filter(function(s) {
        return now - s.created < DURATION;
      });

      strokesRef.current.forEach(function(stroke) {
        var age = now - stroke.created;
        var alpha = Math.max(0, 1 - age / DURATION);
        drawStroke(stroke.points, alpha);
      });

      if (drawingRef.current && currentRef.current.length > 1) {
        drawStroke(currentRef.current, 1);
      }

      rafRef.current = requestAnimationFrame(render);
    };

    window.addEventListener('mousemove', onMove);
    window.addEventListener('mousedown', onDown);
    window.addEventListener('mouseup', onUp);
    document.addEventListener('mouseleave', onLeave);
    rafRef.current = requestAnimationFrame(render);

    return () => {
      window.removeEventListener('resize', resize);
      window.removeEventListener('mousemove', onMove);
      window.removeEventListener('mousedown', onDown);
      window.removeEventListener('mouseup', onUp);
      document.removeEventListener('mouseleave', onLeave);
      cancelAnimationFrame(rafRef.current);
    };
  }, []);

  return (
    <>
      <canvas ref={canvasRef} className="laser-canvas" />
      <div ref={dotRef} className="laser-dot" />
    </>
  );
}

const sound = (() => {
  let ctx = null;
  let muted = true;
  const ensure = () => { if (!ctx) try { ctx = new (window.AudioContext || window.webkitAudioContext)(); } catch(e) {} };
  return {
    setMuted: (m) => { muted = m; if (!m) ensure(); },
    isMuted: () => muted,
    click: () => {
      if (muted) return;
      ensure(); if (!ctx) return;
      const t = ctx.currentTime;
      const o = ctx.createOscillator();
      const g = ctx.createGain();
      o.type = "square";
      o.frequency.setValueAtTime(880, t);
      o.frequency.exponentialRampToValueAtTime(220, t + 0.06);
      g.gain.setValueAtTime(0.04, t);
      g.gain.exponentialRampToValueAtTime(0.0001, t + 0.07);
      o.connect(g).connect(ctx.destination);
      o.start(t); o.stop(t + 0.08);
    },
    coin: () => {
      if (muted) return;
      ensure(); if (!ctx) return;
      const t = ctx.currentTime;
      [988, 1318].forEach((f, i) => {
        const o = ctx.createOscillator(); const g = ctx.createGain();
        o.type = "square"; o.frequency.setValueAtTime(f, t + i*0.07);
        g.gain.setValueAtTime(0.06, t + i*0.07);
        g.gain.exponentialRampToValueAtTime(0.0001, t + i*0.07 + 0.18);
        o.connect(g).connect(ctx.destination);
        o.start(t + i*0.07); o.stop(t + i*0.07 + 0.2);
      });
    },
  };
})();

function useKonami(callback){
  React.useEffect(() => {
    const seq = ["ArrowUp","ArrowUp","ArrowDown","ArrowDown","ArrowLeft","ArrowRight","ArrowLeft","ArrowRight","b","a"];
    let i = 0;
    const onKey = (e) => {
      const k = e.key.length === 1 ? e.key.toLowerCase() : e.key;
      if (k === seq[i]){ i++; if (i === seq.length){ i = 0; callback(); } }
      else { i = (k === seq[0]) ? 1 : 0; }
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [callback]);
}

function useCountUp(target, duration = 1400){
  const [n, setN] = React.useState(0);
  React.useEffect(() => {
    let raf = 0; const start = performance.now();
    const tick = (now) => {
      const t = Math.min(1, (now - start) / duration);
      const eased = 1 - Math.pow(1 - t, 3);
      setN(Math.floor(target * eased));
      if (t < 1) raf = requestAnimationFrame(tick); else setN(target);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [target, duration]);
  return n;
}

Object.assign(window, { LaserPointer, sound, useKonami, useCountUp });
