/* Hero dashboard — a live, product-grade panel that shows the outcomes
   Martz Forge delivers (recovered hours, revenue, fewer errors). Doubles as
   proof of the studio's craft. Canvas draws an ambient system + a live
   climbing area chart; the DOM overlay holds the chip, live badge and KPIs. */

const useCountUp = (target, { duration = 1600, decimals = 0, delay = 0 } = {}) => {
  const [val, setVal] = React.useState(0);
  React.useEffect(() => {
    let raf, t0 = null;
    const tick = (ts) => {
      if (t0 === null) t0 = ts;
      const p = Math.min(1, (ts - t0 - delay) / duration);
      const eased = p <= 0 ? 0 : 1 - Math.pow(1 - p, 3);
      setVal(target * eased);
      if (p < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [target]);
  return decimals ? val.toFixed(decimals) : Math.round(val).toLocaleString('en-US');
};

const HeroCanvas = () => {
  const canvasRef = React.useRef(null);
  React.useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    let raf, w, h, dpr;

    const resize = () => {
      const rect = canvas.getBoundingClientRect();
      dpr = window.devicePixelRatio || 1;
      w = rect.width; h = rect.height;
      canvas.width = w * dpr; canvas.height = h * dpr;
      ctx.setTransform(1, 0, 0, 1, 0, 0); ctx.scale(dpr, dpr);
    };
    resize();
    const ro = new ResizeObserver(resize); ro.observe(canvas);

    // ambient "system" nodes — subtle texture behind the chart
    const NUM = 16, amb = [];
    for (let i = 0; i < NUM; i++) {
      amb.push({
        x: Math.random(), y: Math.random(),
        vx: (Math.random() - 0.5) * 0.00012, vy: (Math.random() - 0.5) * 0.00012,
        r: 1 + Math.random() * 1.8, phase: Math.random() * Math.PI * 2,
        sp: 0.5 + Math.random() * 0.7,
      });
    }

    const clampN = (v, a, b) => Math.max(a, Math.min(b, v));
    let t = 0;

    const draw = () => {
      t += 1 / 60;
      ctx.clearRect(0, 0, w, h);

      // ---- ambient network (dim) ----
      amb.forEach(n => {
        n.x += n.vx; n.y += n.vy;
        if (n.x < 0.04 || n.x > 0.96) n.vx *= -1;
        if (n.y < 0.04 || n.y > 0.96) n.vy *= -1;
      });
      for (let i = 0; i < amb.length; i++) {
        for (let j = i + 1; j < amb.length; j++) {
          const dx = amb[i].x - amb[j].x, dy = amb[i].y - amb[j].y;
          const d = Math.hypot(dx, dy);
          if (d < 0.24) {
            ctx.strokeStyle = `rgba(120,180,160,${(1 - d / 0.24) * 0.08})`;
            ctx.lineWidth = 1;
            ctx.beginPath();
            ctx.moveTo(amb[i].x * w, amb[i].y * h);
            ctx.lineTo(amb[j].x * w, amb[j].y * h);
            ctx.stroke();
          }
        }
      }
      amb.forEach(n => {
        const px = n.x * w, py = n.y * h;
        const pulse = 0.5 + Math.sin(t * n.sp + n.phase) * 0.5;
        ctx.fillStyle = `rgba(140,200,180,${0.12 + pulse * 0.12})`;
        ctx.beginPath(); ctx.arc(px, py, n.r, 0, Math.PI * 2); ctx.fill();
      });

      // ---- live climbing area chart ----
      const padX = 26;
      const cx0 = padX, cx1 = w - padX;
      const cTop = h * 0.315, cBot = h * 0.60;
      const GREEN = '34,197,94', CYAN = '6,182,212';

      // horizontal gridlines
      for (let g = 0; g <= 3; g++) {
        const gy = cTop + (cBot - cTop) * (g / 3);
        ctx.strokeStyle = 'rgba(255,255,255,0.05)'; ctx.lineWidth = 1;
        ctx.beginPath(); ctx.moveTo(cx0, gy); ctx.lineTo(cx1, gy); ctx.stroke();
      }

      const N = 90, pts = [];
      for (let i = 0; i <= N; i++) {
        const fx = i / N;
        const growth = Math.pow(fx, 0.85);
        const wig = 0.05 * Math.sin(fx * 6.5 - t * 1.1)
                  + 0.028 * Math.sin(fx * 15 - t * 1.9)
                  + 0.02 * Math.sin(fx * 3 - t * 0.6);
        const v = clampN(0.12 + growth * 0.72 + wig, 0.05, 0.97);
        pts.push({ x: cx0 + fx * (cx1 - cx0), y: cBot - v * (cBot - cTop) });
      }

      // area fill
      ctx.beginPath();
      ctx.moveTo(pts[0].x, cBot);
      pts.forEach(p => ctx.lineTo(p.x, p.y));
      ctx.lineTo(pts[pts.length - 1].x, cBot);
      ctx.closePath();
      const ga = ctx.createLinearGradient(0, cTop, 0, cBot);
      ga.addColorStop(0, `rgba(${GREEN},0.30)`);
      ga.addColorStop(1, `rgba(${CYAN},0.02)`);
      ctx.fillStyle = ga; ctx.fill();

      // line
      ctx.beginPath();
      pts.forEach((p, i) => i === 0 ? ctx.moveTo(p.x, p.y) : ctx.lineTo(p.x, p.y));
      const gl = ctx.createLinearGradient(cx0, 0, cx1, 0);
      gl.addColorStop(0, `rgb(${GREEN})`); gl.addColorStop(1, `rgb(${CYAN})`);
      ctx.strokeStyle = gl; ctx.lineWidth = 2.6; ctx.lineJoin = 'round';
      ctx.shadowColor = `rgba(${GREEN},0.5)`; ctx.shadowBlur = 10;
      ctx.stroke(); ctx.shadowBlur = 0;

      // travelling data pulse along the line
      const tp = (t * 0.11) % 1;
      const pi = Math.floor(tp * N);
      const pp = pts[pi];
      if (pp) {
        const glow = ctx.createRadialGradient(pp.x, pp.y, 0, pp.x, pp.y, 12);
        glow.addColorStop(0, 'rgba(255,255,255,0.9)');
        glow.addColorStop(1, 'rgba(34,197,94,0)');
        ctx.fillStyle = glow;
        ctx.beginPath(); ctx.arc(pp.x, pp.y, 12, 0, Math.PI * 2); ctx.fill();
      }

      // leading edge marker (the "now" point)
      const last = pts[pts.length - 1];
      ctx.strokeStyle = 'rgba(255,255,255,0.10)'; ctx.lineWidth = 1;
      ctx.setLineDash([3, 3]);
      ctx.beginPath(); ctx.moveTo(last.x, last.y); ctx.lineTo(last.x, cBot); ctx.stroke();
      ctx.setLineDash([]);
      const lp = 0.5 + Math.sin(t * 2.4) * 0.5;
      const lhalo = ctx.createRadialGradient(last.x, last.y, 0, last.x, last.y, 16);
      lhalo.addColorStop(0, `rgba(${CYAN},${0.35 + lp * 0.3})`);
      lhalo.addColorStop(1, `rgba(${CYAN},0)`);
      ctx.fillStyle = lhalo;
      ctx.beginPath(); ctx.arc(last.x, last.y, 16, 0, Math.PI * 2); ctx.fill();
      ctx.fillStyle = `rgb(${CYAN})`;
      ctx.beginPath(); ctx.arc(last.x, last.y, 4, 0, Math.PI * 2); ctx.fill();
      ctx.fillStyle = '#fff';
      ctx.beginPath(); ctx.arc(last.x, last.y, 1.8, 0, Math.PI * 2); ctx.fill();

      raf = requestAnimationFrame(draw);
    };
    draw();
    return () => { cancelAnimationFrame(raf); ro.disconnect(); };
  }, []);

  return <canvas ref={canvasRef} className="nc-canvas" />;
};

const HeroKpi = ({ k, prefix, target, decimals, suffix, dir, grad, delay }) => {
  const val = useCountUp(target, { decimals, delay });
  return (
    <div className="nc-tile">
      <div className="k">{k}</div>
      <div className="v">
        {prefix}<span className={grad ? 'grad' : ''}>{val}</span>
        {suffix && <span className="u">{suffix}</span>}
        <span className={`d ${dir === 'down' ? 'down' : ''}`}>
          <svg width="9" height="9" viewBox="0 0 24 24" fill="currentColor">
            {dir === 'down'
              ? <path d="M12 21 3 8h18z" />
              : <path d="M12 3 21 16H3z" />}
          </svg>
        </span>
      </div>
    </div>
  );
};

const HeroDashboard = () => {
  const delta = useCountUp(32, { duration: 1400 });
  return (
    <div className="nc-card">
      <HeroCanvas />
      <div className="nc-overlay">
        <div className="nc-top">
          <div className="nc-chip"><span className="nc-dot" /> sistema.activo · uptime 99.98%</div>
          <div className="nc-live"><span className="nc-live-dot" /> EN VIVO</div>
        </div>

        <div className="nc-chart-head">
          <span className="nc-chart-label">Ingresos recuperados</span>
          <span className="nc-chart-delta">
            +{delta}%
            <svg width="11" height="11" viewBox="0 0 24 24" fill="currentColor"><path d="M12 3 21 16H3z" /></svg>
          </span>
        </div>

        <div className="nc-tiles">
          <HeroKpi k="Horas / mes" target={127} suffix="h" dir="up" grad delay={100} />
          <HeroKpi k="Ingresos / año" prefix="+$" target={28} suffix="K" dir="up" grad delay={250} />
          <HeroKpi k="Errores" target={0.4} decimals={1} suffix="%" dir="down" delay={400} />
        </div>
      </div>
    </div>
  );
};

window.HeroDashboard = HeroDashboard;
/* keep old name working in case other views reference it */
window.NetworkCanvas = HeroCanvas;
