/* HERO D — confete físico que cai, quica, acumula até a metade e
   revela o logo original da Cheer quando o mouse passa. */

const BRAND_DOTS = ["#FECB39", "#D0A4CC", "#2864AE", "#74C9DE"];
const LOGO_SRC = "cheer-ds/assets/logo/cheer-logo-stacked-white.png";

function HeroD({ fill = 0.5, density = 56, reveal = 150 }) {
  const canvasRef = React.useRef(null);
  const sectionRef = React.useRef(null);

  React.useEffect(() => {
    const canvas = canvasRef.current;
    const section = sectionRef.current;
    if (!canvas || !section) return;
    const ctx = canvas.getContext("2d");
    const reduced = window.Motion && window.Motion.REDUCED;

    // ---- logo image (stickers) ----
    const logo = new Image();
    let logoReady = false;
    logo.onload = () => { logoReady = true; };
    logo.src = LOGO_SRC;

    // ---- config ----
    const GRAVITY = 0.30, BOUNCE = 0.5, FRICTION = 0.986, SUBSTEPS = 4;
    const MOUSE_F = 13, SPAWN_INTERVAL = 60, AVG_AREA = 7400;
    let W = 0, H = 0, dpr = Math.min(2, window.devicePixelRatio || 1);
    let circles = [], spawned = 0, lastSpawn = 0, raf = null, running = true;
    const mouse = { x: -9999, y: -9999, active: false };

    // alvo de quantidade ~ área da "piscina" (largura × altura × fração)
    function targetCount() {
      const t = Math.round((W * H * fill * 0.8 / AVG_AREA) * (density / 56));
      return Math.max(10, Math.min(140, t));
    }

    function resize() {
      W = section.offsetWidth; H = section.offsetHeight;
      dpr = Math.min(2, window.devicePixelRatio || 1);
      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);
    }

    function makeCircle() {
      const isSticker = Math.random() < 0.3;
      const r = isSticker ? 30 + Math.random() * 26 : 26 + Math.random() * 50;
      return {
        x: r + Math.random() * Math.max(1, W - 2 * r),
        y: -r - Math.random() * 80,
        r,
        vx: (Math.random() - 0.5) * 2.4,
        vy: 0.5 + Math.random() * 1.4,
        isSticker,
        color: BRAND_DOTS[(Math.random() * BRAND_DOTS.length) | 0],
        opacity: 0,
        glow: 0,
      };
    }

    function repel(c) {
      const dx = c.x - mouse.x, dy = c.y - mouse.y;
      const range = reveal + c.r, d2 = dx * dx + dy * dy;
      if (d2 < range * range && d2 > 0.01) {
        const d = Math.sqrt(d2), t = 1 - d / range, f = t * t * MOUSE_F;
        c.vx += (dx / d) * f; c.vy += (dy / d) * f;
        c.glow = Math.max(c.glow, t * 0.8);
      }
    }
    function bounds(c) {
      if (c.y + c.r > H) { c.y = H - c.r; c.vy = -Math.abs(c.vy) * BOUNCE; c.vx *= 0.82; }
      if (c.x - c.r < 0) { c.x = c.r; c.vx = Math.abs(c.vx) * BOUNCE; }
      if (c.x + c.r > W) { c.x = W - c.r; c.vx = -Math.abs(c.vx) * BOUNCE; }
    }
    function collide(a, b) {
      const dx = b.x - a.x, dy = b.y - a.y, min = a.r + b.r, d2 = dx * dx + dy * dy;
      if (d2 >= min * min || d2 < 0.0001) return;
      const d = Math.sqrt(d2), nx = dx / d, ny = dy / d, pen = (min - d) * 0.5;
      a.x -= nx * pen; a.y -= ny * pen; b.x += nx * pen; b.y += ny * pen;
      const rv = (b.vx - a.vx) * nx + (b.vy - a.vy) * ny;
      if (rv > 0) return;
      const imp = rv * (1 + BOUNCE) * 0.5;
      a.vx += imp * nx; a.vy += imp * ny; b.vx -= imp * nx; b.vy -= imp * ny;
    }
    function step() {
      const dt = 1 / SUBSTEPS;
      for (let s = 0; s < SUBSTEPS; s++) {
        for (const c of circles) {
          if (mouse.active) repel(c);
          c.vy += GRAVITY * dt;
          c.vx *= Math.pow(FRICTION, dt); c.vy *= Math.pow(FRICTION, dt);
          c.x += c.vx; c.y += c.vy;
          bounds(c);
        }
        for (let i = 0; i < circles.length - 1; i++)
          for (let j = i + 1; j < circles.length; j++) collide(circles[i], circles[j]);
      }
      for (const c of circles) { c.opacity = Math.min(1, c.opacity + 0.04); c.glow = Math.max(0, c.glow - 0.05); }
    }

    // fill target: topo da pilha que queremos atingir (até `fill` da altura)
    function settledTop() {
      let top = H;
      for (const c of circles) {
        if (Math.abs(c.vy) < 0.8 && c.y > H * 0.25) top = Math.min(top, c.y - c.r);
      }
      return top;
    }
    void settledTop;

    function drawPlain(c) {
      ctx.save(); ctx.globalAlpha = c.opacity;
      if (c.glow > 0.01) {
        const g = ctx.createRadialGradient(c.x, c.y, c.r * 0.5, c.x, c.y, c.r * 1.7);
        g.addColorStop(0, c.color + Math.round(c.glow * 90).toString(16).padStart(2, "0"));
        g.addColorStop(1, c.color + "00");
        ctx.beginPath(); ctx.arc(c.x, c.y, c.r * 1.7, 0, 6.2832); ctx.fillStyle = g; ctx.fill();
      }
      ctx.beginPath(); ctx.arc(c.x, c.y, c.r, 0, 6.2832); ctx.fillStyle = c.color; ctx.fill();
      ctx.restore();
    }
    function drawSticker(c) {
      ctx.save(); ctx.globalAlpha = c.opacity;
      // corpo preto
      ctx.beginPath(); ctx.arc(c.x, c.y, c.r, 0, 6.2832); ctx.fillStyle = "#0a0a0b"; ctx.fill();
      // anel degradê (brand)
      ctx.lineWidth = Math.max(2.5, c.r * 0.1);
      if (ctx.createConicGradient) {
        const ring = ctx.createConicGradient(0, c.x, c.y);
        ring.addColorStop(0.00, "#FECB39"); ring.addColorStop(0.33, "#D0A4CC");
        ring.addColorStop(0.66, "#2864AE"); ring.addColorStop(0.85, "#74C9DE");
        ring.addColorStop(1.00, "#FECB39");
        ctx.strokeStyle = ring;
      } else { ctx.strokeStyle = "#74C9DE"; }
      ctx.beginPath(); ctx.arc(c.x, c.y, c.r - ctx.lineWidth / 2, 0, 6.2832); ctx.stroke();
      // logo dentro (clip)
      if (logoReady) {
        ctx.save();
        ctx.beginPath(); ctx.arc(c.x, c.y, c.r * 0.82, 0, 6.2832); ctx.clip();
        const box = c.r * 1.3, ar = logo.naturalWidth / logo.naturalHeight;
        let w = box, h = box / ar; if (h > box) { h = box; w = box * ar; }
        ctx.drawImage(logo, c.x - w / 2, c.y - h / 2, w, h);
        ctx.restore();
      }
      ctx.restore();
    }
    function drawRing() {
      if (!mouse.active) return;
      ctx.save();
      ctx.beginPath(); ctx.arc(mouse.x, mouse.y, reveal, 0, 6.2832);
      ctx.strokeStyle = "rgba(255,255,255,0.08)"; ctx.lineWidth = 1; ctx.stroke();
      ctx.restore();
    }
    function draw() {
      ctx.clearRect(0, 0, W, H);
      for (const c of circles) c.isSticker ? drawSticker(c) : drawPlain(c);
      drawRing();
    }

    function loop(t) {
      if (!running) return;
      if (circles.length < targetCount() && t - lastSpawn > SPAWN_INTERVAL) {
        circles.push(makeCircle()); spawned++; lastSpawn = t;
      }
      step(); draw();
      canvas.setAttribute("data-n", circles.length);
      raf = requestAnimationFrame(loop);
    }
    window.__heroD = { get circles() { return circles; }, dims: () => ({ W, H }), mouse };

    // ---- events ----
    function onMove(e) {
      const r = section.getBoundingClientRect();
      const pt = e.touches ? e.touches[0] : e;
      mouse.x = pt.clientX - r.left; mouse.y = pt.clientY - r.top; mouse.active = true;
    }
    function onLeave() { mouse.active = false; mouse.x = mouse.y = -9999; }
    function onResize() { resize(); for (const c of circles) { c.x = Math.max(c.r, Math.min(W - c.r, c.x)); if (c.y > H - c.r) c.y = H - c.r; } }

    resize();
    section.addEventListener("mousemove", onMove);
    section.addEventListener("mouseleave", onLeave);
    section.addEventListener("touchmove", onMove, { passive: true });
    section.addEventListener("touchend", onLeave);
    window.addEventListener("resize", onResize);

    if (reduced) {
      // sem animação: preenche estaticamente
      const N = targetCount();
      for (let i = 0; i < N; i++) { const c = makeCircle(); c.y = H - c.r - Math.random() * H * fill; c.opacity = 1; circles.push(c); }
      let tries = 0; const settle = () => { step(); tries++; if (tries < 60) requestAnimationFrame(settle); else draw(); };
      logo.complete ? settle() : (logo.onload = () => { logoReady = true; settle(); });
    } else {
      raf = requestAnimationFrame(loop);
    }

    return () => {
      running = false;
      if (raf) cancelAnimationFrame(raf);
      section.removeEventListener("mousemove", onMove);
      section.removeEventListener("mouseleave", onLeave);
      section.removeEventListener("touchmove", onMove);
      section.removeEventListener("touchend", onLeave);
      window.removeEventListener("resize", onResize);
    };
  }, [fill, density, reveal]);

  return (
    <section className="hero hero--d" id="top" ref={sectionRef}>
      <img className="heroD__logo" src={LOGO_SRC} alt="cheer design"
        style={{ top: ((1 - fill / 2) * 100) + "%" }} />
      <canvas className="heroD__canvas" ref={canvasRef}></canvas>
      <div className="heroD__scrim"></div>
      <div className="heroD__content">
        <div className="hero__eyebrow eyebrow eyebrow--ondark">
          <span className="eyebrow__rule"></span>Estúdio de branding e estratégia
        </div>
        <h1 className="hero__title">Somos o parceiro estratégico de negócios que entendem
          que marca não é <span className="grad-text">só estética</span></h1>
        <p className="hero__sub lead">Posicionamos fundadores, experts e empresas como a
          escolha óbvia para o cliente certo.</p>
        <div className="hero__cta">
          <window.HeroActions size="lg" />
        </div>
      </div>
      <div className="heroD__hint">
        <window.Icon.Spark /> Mova o cursor para revelar o logo
      </div>
    </section>
  );
}

window.HeroD = HeroD;
