// particle-text.jsx — Ported from particle-text-effect.tsx (TypeScript → vanilla JS)
// No imports needed. Pure React + Canvas.

// ─── Particle class ──────────────────────────────────────────────────────────
class Particle {
  constructor() {
    this.pos   = { x: 0, y: 0 };
    this.vel   = { x: 0, y: 0 };
    this.acc   = { x: 0, y: 0 };
    this.target = { x: 0, y: 0 };

    this.closeEnoughTarget = 100;
    this.maxSpeed  = 1.0;
    this.maxForce  = 0.1;
    this.particleSize = 10;
    this.isKilled = false;

    this.startColor  = { r: 0, g: 0, b: 0 };
    this.targetColor = { r: 0, g: 0, b: 0 };
    this.colorWeight = 0;
    this.colorBlendRate = 0.01;
  }

  move() {
    const dist = Math.hypot(this.pos.x - this.target.x, this.pos.y - this.target.y);
    const proximityMult = dist < this.closeEnoughTarget ? dist / this.closeEnoughTarget : 1;

    const dx = this.target.x - this.pos.x;
    const dy = this.target.y - this.pos.y;
    const mag = Math.hypot(dx, dy);
    const tx = mag > 0 ? (dx / mag) * this.maxSpeed * proximityMult : 0;
    const ty = mag > 0 ? (dy / mag) * this.maxSpeed * proximityMult : 0;

    let sx = tx - this.vel.x;
    let sy = ty - this.vel.y;
    const sm = Math.hypot(sx, sy);
    if (sm > 0) { sx = (sx / sm) * this.maxForce; sy = (sy / sm) * this.maxForce; }

    this.acc.x += sx; this.acc.y += sy;
    this.vel.x += this.acc.x; this.vel.y += this.acc.y;
    this.pos.x += this.vel.x; this.pos.y += this.vel.y;
    this.acc.x = 0; this.acc.y = 0;
  }

  draw(ctx, drawAsPoints) {
    if (this.colorWeight < 1.0) {
      this.colorWeight = Math.min(this.colorWeight + this.colorBlendRate, 1.0);
    }
    const r = Math.round(this.startColor.r + (this.targetColor.r - this.startColor.r) * this.colorWeight);
    const g = Math.round(this.startColor.g + (this.targetColor.g - this.startColor.g) * this.colorWeight);
    const b = Math.round(this.startColor.b + (this.targetColor.b - this.startColor.b) * this.colorWeight);

    ctx.fillStyle = `rgb(${r},${g},${b})`;
    if (drawAsPoints) {
      ctx.fillRect(this.pos.x, this.pos.y, 2, 2);
    } else {
      ctx.beginPath();
      ctx.arc(this.pos.x, this.pos.y, this.particleSize / 2, 0, Math.PI * 2);
      ctx.fill();
    }
  }

  kill(w, h) {
    if (!this.isKilled) {
      const rp = _randomPos(w / 2, h / 2, (w + h) / 2);
      this.target.x = rp.x;
      this.target.y = rp.y;

      this.startColor = {
        r: this.startColor.r + (this.targetColor.r - this.startColor.r) * this.colorWeight,
        g: this.startColor.g + (this.targetColor.g - this.startColor.g) * this.colorWeight,
        b: this.startColor.b + (this.targetColor.b - this.startColor.b) * this.colorWeight,
      };
      this.targetColor = { r: 0, g: 0, b: 0 };
      this.colorWeight = 0;
      this.isKilled = true;
    }
  }
}

function _randomPos(cx, cy, mag) {
  const rx = Math.random() * 1000;
  const ry = Math.random() * 500;
  const dx = rx - cx;
  const dy = ry - cy;
  const m = Math.hypot(dx, dy);
  return m > 0
    ? { x: cx + (dx / m) * mag, y: cy + (dy / m) * mag }
    : { x: cx, y: cy };
}

// ─── Component ────────────────────────────────────────────────────────────────
const DEFAULT_WORDS = ['AUTOMATE', 'SAVE TIME', 'GROW FASTER', 'NO MORE BUSYWORK', 'JAWWAD'];

const ParticleTextEffect = ({ words = DEFAULT_WORDS }) => {
  const canvasRef    = React.useRef(null);
  const rafRef       = React.useRef(null);
  const particlesRef = React.useRef([]);
  const frameRef     = React.useRef(0);
  const wordIdxRef   = React.useRef(0);
  const mouseRef     = React.useRef({ x: 0, y: 0, isPressed: false, isRightClick: false });

  const PIXEL_STEPS  = 6;
  const DRAW_POINTS  = true;

  function nextWord(word, canvas) {
    const off = document.createElement('canvas');
    off.width  = canvas.width;
    off.height = canvas.height;
    const octx = off.getContext('2d');

    octx.fillStyle = 'white';
    octx.font = 'bold 100px Arial';
    octx.textAlign    = 'center';
    octx.textBaseline = 'middle';
    octx.fillText(word, canvas.width / 2, canvas.height / 2);

    const imgData = octx.getImageData(0, 0, canvas.width, canvas.height);
    const pixels  = imgData.data;

    const newColor = {
      r: Math.random() * 255,
      g: Math.random() * 255,
      b: Math.random() * 255,
    };

    const ps = particlesRef.current;
    let pi = 0;

    // Collect + shuffle indices for fluid motion
    const coords = [];
    for (let i = 0; i < pixels.length; i += PIXEL_STEPS * 4) coords.push(i);
    for (let i = coords.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [coords[i], coords[j]] = [coords[j], coords[i]];
    }

    for (const ci of coords) {
      if (pixels[ci + 3] > 0) {
        const x = (ci / 4) % canvas.width;
        const y = Math.floor(ci / 4 / canvas.width);

        let p;
        if (pi < ps.length) {
          p = ps[pi];
          p.isKilled = false;
          pi++;
        } else {
          p = new Particle();
          const rp = _randomPos(canvas.width / 2, canvas.height / 2, (canvas.width + canvas.height) / 2);
          p.pos.x = rp.x; p.pos.y = rp.y;
          p.maxSpeed = Math.random() * 6 + 4;
          p.maxForce = p.maxSpeed * 0.05;
          p.particleSize  = Math.random() * 6 + 6;
          p.colorBlendRate = Math.random() * 0.0275 + 0.0025;
          ps.push(p);
        }

        p.startColor = {
          r: p.startColor.r + (p.targetColor.r - p.startColor.r) * p.colorWeight,
          g: p.startColor.g + (p.targetColor.g - p.startColor.g) * p.colorWeight,
          b: p.startColor.b + (p.targetColor.b - p.startColor.b) * p.colorWeight,
        };
        p.targetColor  = newColor;
        p.colorWeight  = 0;
        p.target.x = x;
        p.target.y = y;
      }
    }

    for (let i = pi; i < ps.length; i++) ps[i].kill(canvas.width, canvas.height);
  }

  function animate() {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    const ps  = particlesRef.current;

    // motion blur trail
    ctx.fillStyle = 'rgba(0,0,0,0.1)';
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    for (let i = ps.length - 1; i >= 0; i--) {
      ps[i].move();
      ps[i].draw(ctx, DRAW_POINTS);
      if (ps[i].isKilled) {
        const { x, y } = ps[i].pos;
        if (x < 0 || x > canvas.width || y < 0 || y > canvas.height) {
          ps.splice(i, 1);
        }
      }
    }

    // Right-click hold destroys nearby particles
    const m = mouseRef.current;
    if (m.isPressed && m.isRightClick) {
      ps.forEach(p => {
        if (Math.hypot(p.pos.x - m.x, p.pos.y - m.y) < 50) p.kill(canvas.width, canvas.height);
      });
    }

    frameRef.current++;
    if (frameRef.current % 240 === 0) {
      wordIdxRef.current = (wordIdxRef.current + 1) % words.length;
      nextWord(words[wordIdxRef.current], canvas);
    }

    rafRef.current = requestAnimationFrame(animate);
  }

  React.useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;

    canvas.width  = 1000;
    canvas.height = 500;

    nextWord(words[0], canvas);
    animate();

    const onDown  = e => {
      mouseRef.current.isPressed    = true;
      mouseRef.current.isRightClick = e.button === 2;
      const r = canvas.getBoundingClientRect();
      mouseRef.current.x = e.clientX - r.left;
      mouseRef.current.y = e.clientY - r.top;
    };
    const onUp    = () => { mouseRef.current.isPressed = false; mouseRef.current.isRightClick = false; };
    const onMove  = e => {
      const r = canvas.getBoundingClientRect();
      mouseRef.current.x = e.clientX - r.left;
      mouseRef.current.y = e.clientY - r.top;
    };
    const onMenu  = e => e.preventDefault();

    canvas.addEventListener('mousedown',    onDown);
    canvas.addEventListener('mouseup',      onUp);
    canvas.addEventListener('mousemove',    onMove);
    canvas.addEventListener('contextmenu',  onMenu);

    return () => {
      if (rafRef.current) cancelAnimationFrame(rafRef.current);
      canvas.removeEventListener('mousedown',   onDown);
      canvas.removeEventListener('mouseup',     onUp);
      canvas.removeEventListener('mousemove',   onMove);
      canvas.removeEventListener('contextmenu', onMenu);
    };
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return (
    <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', background: '#000', padding: '2rem' }}>
      <canvas
        ref={canvasRef}
        style={{
          border: '1px solid rgba(255,255,255,0.08)',
          borderRadius: '12px',
          boxShadow: '0 24px 64px rgba(0,0,0,0.8)',
          maxWidth: '100%',
          height: 'auto',
          cursor: 'crosshair',
        }}
      />
      <div style={{ marginTop: '1rem', color: 'rgba(255,255,255,0.5)', fontSize: '0.78rem', textAlign: 'center' }}>
        <p style={{ marginBottom: '4px', color: 'rgba(255,255,255,0.7)' }}>Particle Text Effect</p>
        <p>Right-click &amp; hold to destroy particles · words cycle every 4 s</p>
      </div>
    </div>
  );
};

window.ParticleTextEffect = ParticleTextEffect;
