/* ============================================================
   FINAZ — Pantalla en vivo · GRÁFICO PRINCIPAL
   Tema "Ecología generativa" (Entangled Others):
   velas verde/magenta + media glow + micelio creciente + esporas.
   Conserva crosshair, leyenda OHLC y marcadores de evento interactivos.
   ============================================================ */
const { useState: useSC, useContext: useCC, useRef: useRC, useEffect: useEC } = React;

function clampN(v, a, b) { return v < a ? a : v > b ? b : v; }
function eu(n, d = 2) { return n.toLocaleString("es-ES", { minimumFractionDigits: d, maximumFractionDigits: d }); }

const TVT = {
  up: "#6ce4a6", down: "#ff7d9e", ma: "#9fe06a", accent: "#6ce4a6",
  accent2: "#ff5fa8", accent3: "#9fe06a", grid: "rgba(120,210,170,.06)",
  axis: "#5f8a76", sub: "#79ab93", ink: "#eafff4", bg: "#06120d", panel: "#0a1813",
};

/* ---- Lienzo de esporas (motor cinético, modo spores) ---- */
function SporeCanvas({ active }) {
  const cvRef = useRC(null), wrapRef = useRC(null);
  useEC(() => {
    const cv = cvRef.current, wrap = wrapRef.current;
    if (!cv || !wrap) return;
    const ctx = cv.getContext("2d");
    const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    let W = 0, H = 0, dpr = Math.min(2, window.devicePixelRatio || 1), raf;
    const cols = [TVT.accent, TVT.accent3, TVT.accent2];
    const rnd = (a, b) => a + Math.random() * (b - a);
    let parts = [];
    function resize() {
      const r = wrap.getBoundingClientRect(); W = r.width; H = r.height;
      cv.width = W * dpr; cv.height = H * dpr; cv.style.width = W + "px"; cv.style.height = H + "px";
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
    }
    const ro = new ResizeObserver(resize); ro.observe(wrap); resize();
    function init() {
      parts = [];
      for (let i = 0; i < 80; i++) parts.push({
        x: Math.random(), y: Math.random(),
        vx: rnd(-0.0005, 0.0005), vy: rnd(-0.0013, -0.0003),
        r: rnd(0.5, 2.0), col: cols[(Math.random() * cols.length) | 0],
        a: rnd(0.15, 0.7), ph: rnd(0, Math.PI * 2),
      });
    }
    init();
    function frame(now) {
      ctx.clearRect(0, 0, W, H);
      ctx.globalCompositeOperation = "lighter";
      parts.forEach(p => {
        p.x += p.vx; p.y += p.vy;
        if (p.y < 0.02) { p.y = 0.98; p.x = Math.random(); }
        if (p.x < 0) p.x = 1; if (p.x > 1) p.x = 0;
        const tw = 0.55 + 0.45 * Math.abs(Math.sin(now * 0.001 + p.ph));
        ctx.globalAlpha = p.a * tw;
        ctx.fillStyle = p.col;
        ctx.beginPath(); ctx.arc(p.x * W, p.y * H, p.r, 0, 7); ctx.fill();
      });
      ctx.globalAlpha = 1;
      if (!reduce) raf = requestAnimationFrame(frame);
    }
    if (reduce) frame(0); else raf = requestAnimationFrame(frame);
    return () => { cancelAnimationFrame(raf); ro.disconnect(); };
  }, [active]);
  return React.createElement("div", { ref: wrapRef, className: "lv-tvcanvas" },
    React.createElement("canvas", { ref: cvRef }));
}

function LiveCandleChart({ depth, w = 880, h = 320 }) {
  const L = window.LIVE, F = window.FINAZ_FACTS;
  const { hl, setHl, setSel } = useCC(LiveCtx);
  const candles = L.candles, ma = L.ma, N = candles.length;
  const [hoverIdx, setHoverIdx] = useSC(null);
  const [cross, setCross] = useSC(null);

  const padT = 14, padB = 24, padL = 8, padR = 70;
  const iw = w - padL - padR, ih = h - padT - padB;
  let lo = Math.min(...candles.map(c => c.l)), hi = Math.max(...candles.map(c => c.h));
  L.levels.forEach(lv => { lo = Math.min(lo, lv.v); hi = Math.max(hi, lv.v); });
  lo -= 10; hi += 10; const range = hi - lo || 1;
  const slot = iw / N, cw = Math.max(1.6, Math.min(slot * 0.62, 9));
  const cx = i => padL + slot * i + slot / 2;
  const xv = v => padT + ih - ((v - lo) / range) * ih;
  const yToPrice = py => lo + (ih - (py - padT)) / ih * range;
  const baseY = padT + ih;

  const svgRef = useRC(null);
  function onMove(e) {
    const r = svgRef.current.getBoundingClientRect();
    const px = (e.clientX - r.left) / r.width * w;
    const py = (e.clientY - r.top) / r.height * h;
    const idx = clampN(Math.round((px - padL - slot / 2) / slot), 0, N - 1);
    setHoverIdx(idx); setCross({ x: cx(idx), y: clampN(py, padT, padT + ih) });
  }
  function onLeave() { setHoverIdx(null); setCross(null); }

  const leg = candles[hoverIdx == null ? N - 1 : hoverIdx];
  const legUp = leg.c >= leg.o;
  const maPts = ma.map((v, i) => `${cx(i)},${xv(v)}`).join(" ");
  const maArea = `${cx(0)},${baseY} ${maPts} ${cx(N - 1)},${baseY}`;
  const showLegend = depth >= 1;
  const showVol = depth >= 1;
  const shownMarkers = depth === 0 ? L.markers.filter(m => m.impacto === "alto") : L.markers;

  const step = 40; const t0 = Math.ceil(lo / step) * step; const ticks = [];
  for (let v = t0; v < hi; v += step) ticks.push(v);
  const timeTicks = [0, 24, 48, 72, N - 1];

  // Micelio: filamentos que crecen desde la base hasta el cuerpo de la vela
  const fils = [];
  for (let i = 0; i < N; i += 4) {
    const c = candles[i];
    const top = xv(Math.max(c.o, c.c));
    const sway = 7 * Math.sin(i * 0.7);
    const mid = (baseY + top) / 2;
    const d = `M${cx(i)},${baseY} Q${cx(i) + sway},${mid} ${cx(i)},${top}`;
    const branch = `M${cx(i)},${mid} l${sway > 0 ? 7 : -7},-6`;
    fils.push(
      <g key={"f" + i} opacity="0.5">
        <path d={d} fill="none" stroke={TVT.accent} strokeWidth="0.7" opacity="0.3" />
        <path d={branch} fill="none" stroke={TVT.accent3} strokeWidth="0.55" opacity="0.26" />
        <circle cx={cx(i)} cy={top} r="1.5" fill={TVT.accent2} opacity="0.55" />
      </g>
    );
  }

  return (
    <div className="lv-tv">
      <SporeCanvas active={depth} />

      {showLegend && (
        <div className="lv-tvlegend">
          <span className="lv-tvl"><i>O</i>{eu(leg.o)}</span>
          <span className="lv-tvl"><i>H</i>{eu(leg.h)}</span>
          <span className="lv-tvl"><i>L</i>{eu(leg.l)}</span>
          <span className="lv-tvl"><i>C</i><b style={{ color: legUp ? TVT.up : TVT.down }}>{eu(leg.c)}</b></span>
          {showVol && <span className="lv-tvl"><i>Vol</i>{eu(leg.v, 0)}K</span>}
          <span className="lv-tvl lv-tvtime">{F.episode.fecha.split(",")[1]} · {leg.t}</span>
          {hoverIdx != null && <span className="lv-tvhint">○ punto inspeccionado</span>}
        </div>
      )}

      <svg ref={svgRef} viewBox={`0 0 ${w} ${h}`} width="100%" style={{ display: "block" }}
        onMouseMove={onMove} onMouseLeave={onLeave}>
        <defs>
          <linearGradient id="lv-maarea" x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%" stopColor={TVT.accent} stopOpacity="0.16" />
            <stop offset="100%" stopColor={TVT.accent} stopOpacity="0" />
          </linearGradient>
          <filter id="lv-glow" x="-30%" y="-60%" width="160%" height="220%">
            <feGaussianBlur stdDeviation="3.4" result="b" />
            <feMerge><feMergeNode in="b" /><feMergeNode in="SourceGraphic" /></feMerge>
          </filter>
        </defs>

        {/* banda de evento */}
        <rect x={padL + slot * L.chartBand.from} y={padT} width={slot * (L.chartBand.to - L.chartBand.from)} height={ih} fill={L.chartBand.color} />

        {/* rejilla + eje de precios */}
        {ticks.map((v, i) => (
          <g key={i}>
            <line x1={padL} x2={padL + iw} y1={xv(v)} y2={xv(v)} stroke={TVT.grid} strokeWidth="1" />
            <text x={w - padR + 8} y={xv(v) + 3} fontSize="10" fill={TVT.axis} fontFamily="'Spline Sans Mono',monospace">{eu(v, 0)}</text>
          </g>
        ))}

        {/* micelio (detrás de las velas) */}
        <g>{fils}</g>

        {/* media móvil con glow (la "línea viva") */}
        <polygon points={maArea} fill="url(#lv-maarea)" />
        <polyline points={maPts} fill="none" stroke={TVT.ma} strokeWidth="1.8" strokeLinejoin="round" opacity="0.95" filter="url(#lv-glow)" />

        {/* velas */}
        {candles.map((c, i) => {
          const up = c.c >= c.o, col = up ? TVT.up : TVT.down;
          const bt = xv(Math.max(c.o, c.c)), bb = xv(Math.min(c.o, c.c));
          return (
            <g key={i}>
              <line x1={cx(i)} x2={cx(i)} y1={xv(c.h)} y2={xv(c.l)} stroke={col} strokeWidth="1" opacity="0.92" />
              <rect x={cx(i) - cw / 2} y={bt} width={cw} height={Math.max(1, bb - bt)} fill={col} rx="0.5" opacity="0.95" />
            </g>
          );
        })}

        {/* líneas de referencia */}
        {L.levels.map((lv, i) => (
          <g key={i}>
            <line x1={padL} x2={padL + iw} y1={xv(lv.v)} y2={xv(lv.v)} stroke={lv.color} strokeWidth={lv.strong ? 1.3 : 1}
              strokeDasharray={lv.style === "dot" ? "2 4" : "6 4"} opacity={lv.strong ? 0.9 : 0.55} />
            <g transform={`translate(${w - padR + 2},${xv(lv.v)})`}>
              <rect x="0" y="-8" width={padR - 4} height="16" rx="3" fill={lv.color} />
              <text x={(padR - 4) / 2} y="3.5" fontSize="9.5" fill="#06120d" textAnchor="middle" fontFamily="'Spline Sans Mono',monospace" fontWeight="600">{eu(lv.v, 0)}</text>
            </g>
            {lv.both && <text x={padL + 4} y={xv(lv.v) - 4} fontSize="10" fill={lv.color} fontFamily="'Spline Sans Mono',monospace" fontWeight="600">{eu(lv.v, 0)}</text>}
          </g>
        ))}

        {/* marcadores de evento */}
        {shownMarkers.map((m, i) => {
          const on = hl.set.has(m.newsId);
          const mx = cx(m.idx), my = xv(candles[m.idx].l) + 6;
          const cy = padT + 4 + (i % 2) * 22;
          const label = `${m.hora} ${m.short}`;
          const lw = label.length * 6.3 + 24;
          const col = m.impacto === "alto" ? TVT.accent2 : m.impacto === "medio" ? TVT.accent3 : TVT.sub;
          return (
            <g key={i} className="lv-marker" style={{ cursor: "pointer" }}
              onMouseEnter={() => setHl({ set: new Set([m.newsId, ...(L.news.find(n => n.id === m.newsId)?.affects || [])]) })}
              onMouseLeave={() => setHl({ set: new Set() })}
              onClick={() => setSel({ type: "news", id: m.newsId })}>
              <line x1={mx} x2={mx} y1={cy + 9} y2={my} stroke={col} strokeWidth={on ? 1.6 : 1} strokeDasharray="4 3" opacity={on ? 1 : 0.6} />
              <circle cx={mx} cy={my} r={on ? 5.5 : 4} fill={col} stroke={TVT.bg} strokeWidth="1.5">
                {on && <animate attributeName="r" values="4.5;7;4.5" dur="1.3s" repeatCount="indefinite" />}
              </circle>
              <g transform={`translate(${clampN(mx - lw / 2, padL, padL + iw - lw)},${cy - 9})`}>
                <rect width={lw} height="18" rx="5" fill={on ? "#13241a" : "#0c1812"} stroke={col} strokeWidth={on ? 1.2 : 0.8} opacity={on ? 1 : 0.94} />
                <circle cx="10" cy="9" r="3" fill={col} />
                <text x="18" y="12.5" fontSize="10" fill={on ? "#fff" : "#b9d3c4"} fontFamily="'Schibsted Grotesk',sans-serif" fontWeight="600">{label}</text>
              </g>
            </g>
          );
        })}

        {/* crosshair */}
        {cross && (
          <g pointerEvents="none">
            <line x1={cross.x} x2={cross.x} y1={padT} y2={padT + ih} stroke={TVT.accent} strokeWidth="1" strokeDasharray="3 3" opacity="0.45" />
            <line x1={padL} x2={padL + iw} y1={cross.y} y2={cross.y} stroke={TVT.accent} strokeWidth="1" strokeDasharray="3 3" opacity="0.45" />
            <g transform={`translate(${w - padR + 2},${cross.y})`}>
              <rect x="0" y="-8" width={padR - 4} height="16" rx="3" fill="#1f4030" stroke={TVT.accent} strokeWidth="0.8" />
              <text x={(padR - 4) / 2} y="3.5" fontSize="9.5" fill={TVT.ink} textAnchor="middle" fontFamily="'Spline Sans Mono',monospace" fontWeight="600">{eu(yToPrice(cross.y), 0)}</text>
            </g>
          </g>
        )}

        {/* eje de tiempo */}
        {timeTicks.map((i, k) => (
          <text key={k} x={cx(i)} y={h - 7} fontSize="9.5" fill={TVT.axis} textAnchor={k === 0 ? "start" : k === timeTicks.length - 1 ? "end" : "middle"} fontFamily="'Spline Sans Mono',monospace">{candles[i].t}</text>
        ))}
      </svg>
    </div>
  );
}

window.LiveCandleChart = LiveCandleChart;
