// fx.jsx — code rain background + glitch text + scanline

const { useEffect, useRef, useState } = React;

function CodeRain({ intensity = 'heavy' }) {
  const canvasRef = useRef(null);
  useEffect(() => {
    if (intensity === 'off') return;
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    let w, h, cols, drops;
    const fontSize = 14;
    const chars = 'アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲン0123456789'.split('');

    function resize() {
      w = canvas.width = canvas.offsetWidth * window.devicePixelRatio;
      h = canvas.height = canvas.offsetHeight * window.devicePixelRatio;
      cols = Math.floor(w / (fontSize * window.devicePixelRatio));
      drops = Array(cols).fill(0).map(() => Math.random() * -50);
    }
    resize();
    window.addEventListener('resize', resize);

    const fadeAlpha = intensity === 'subtle' ? 0.12 : intensity === 'heavy' ? 0.06 : 0.04;
    const trailColor = intensity === 'subtle' ? 'rgba(57,255,122,0.35)' : intensity === 'heavy' ? 'rgba(57,255,122,0.7)' : 'rgba(57,255,122,0.85)';
    const headColor = '#caffd9';

    let raf;
    function draw() {
      ctx.fillStyle = `rgba(2,8,5,${fadeAlpha})`;
      ctx.fillRect(0, 0, w, h);
      ctx.font = `${fontSize * window.devicePixelRatio}px JetBrains Mono, monospace`;
      for (let i = 0; i < cols; i++) {
        const ch = chars[Math.floor(Math.random() * chars.length)];
        const x = i * fontSize * window.devicePixelRatio;
        const y = drops[i] * fontSize * window.devicePixelRatio;
        // head
        ctx.fillStyle = headColor;
        ctx.fillText(ch, x, y);
        // trail (previous char)
        ctx.fillStyle = trailColor;
        ctx.fillText(chars[Math.floor(Math.random() * chars.length)], x, y - fontSize * window.devicePixelRatio);
        if (y > h && Math.random() > 0.975) drops[i] = 0;
        drops[i] += intensity === 'subtle' ? 0.4 : intensity === 'heavy' ? 0.7 : 1.0;
      }
      raf = requestAnimationFrame(draw);
    }
    draw();
    return () => { cancelAnimationFrame(raf); window.removeEventListener('resize', resize); };
  }, [intensity]);

  if (intensity === 'off') return null;
  const opacity = intensity === 'subtle' ? 0.15 : intensity === 'heavy' ? 0.32 : 0.55;
  return (
    <canvas
      ref={canvasRef}
      style={{
        position: 'fixed', inset: 0, width: '100%', height: '100%',
        pointerEvents: 'none', zIndex: 0, opacity,
      }}
    />
  );
}

function Scanline({ intensity = 'heavy' }) {
  if (intensity === 'off') return null;
  const op = intensity === 'subtle' ? 0.04 : intensity === 'heavy' ? 0.07 : 0.11;
  return (
    <div style={{
      position: 'fixed', inset: 0, pointerEvents: 'none', zIndex: 9000,
      backgroundImage: `linear-gradient(rgba(57,255,122,${op}) 50%, rgba(0,0,0,0) 50%)`,
      backgroundSize: '100% 3px',
      mixBlendMode: 'overlay',
    }} />
  );
}

function GlitchText({ children, className = '', style = {} }) {
  return (
    <span className={`glitch ${className}`} data-text={typeof children === 'string' ? children : ''} style={style}>
      {children}
    </span>
  );
}

function GlitchIntro({ onDone }) {
  const [phase, setPhase] = useState(0);
  const [boot, setBoot] = useState([]);

  useEffect(() => {
    const lines = [
      '> INITIALIZING SIGNAL HUB...',
      '> CONNECTING TO MARKET FEED [NYSE / NASDAQ / ARCA]...',
      '> LOADING PATTERN RECOGNITION MODELS [14/14]...',
      '> CALIBRATING VOLUME ANALYTICS [30D ROLLING]...',
      '> SUBSCRIBING TO REAL-TIME TICKERS [12 SYMBOLS]...',
      '> AUTHORIZED. WELCOME TO THE GRID.',
    ];
    let i = 0;
    const id = setInterval(() => {
      if (i < lines.length) {
        setBoot(b => [...b, lines[i]]);
        i++;
      } else {
        clearInterval(id);
        setTimeout(() => setPhase(1), 350);
        setTimeout(() => onDone(), 1400);
      }
    }, 220);
    return () => clearInterval(id);
  }, []);

  return (
    <div style={{
      position: 'fixed', inset: 0, zIndex: 10000, background: '#020805',
      display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
      fontFamily: 'JetBrains Mono, monospace', color: '#39ff7a',
      animation: phase === 1 ? 'introOut 0.9s ease-in forwards' : '',
    }}>
      <div style={{ width: '60ch', maxWidth: '90vw' }}>
        <pre style={{
          fontFamily: 'JetBrains Mono, monospace', fontSize: 11, lineHeight: 1.5,
          color: '#39ff7a', textShadow: '0 0 8px rgba(57,255,122,0.5)',
          margin: 0, whiteSpace: 'pre',
        }}>
{`╔══════════════════════════════════════════════════════════╗
║   ████████ ███████  █████   █████  ████████ ███    ██   ║
║      ██    ██   ██  ██   ██ ██  ██    ██    ████   ██   ║
║      ██    ██████   █████   █████     ██    ██ ██  ██   ║
║      ██    ██   ██  ██   ██ ██  ██    ██    ██  ██ ██   ║
║      ██    ██   ██  ██   ██ ██   ██   ██    ██   ████   ║
║          SIGNAL HUB · v2.6 · MATRIX TERMINAL             ║
╚══════════════════════════════════════════════════════════╝`}
        </pre>
        <div style={{ marginTop: 18, fontSize: 12, lineHeight: 1.7 }}>
          {boot.map((l, i) => (
            <div key={i} style={{ animation: 'fadein 0.2s ease-out' }}>{l}</div>
          ))}
          <span style={{ animation: 'blink 1s step-end infinite' }}>█</span>
        </div>
      </div>
    </div>
  );
}

window.CodeRain = CodeRain;
window.Scanline = Scanline;
window.GlitchText = GlitchText;
window.GlitchIntro = GlitchIntro;
