// ====================================================================
// CHARTS — SVG ligero, sin dependencias. Colores desde tokens CSS.
// ====================================================================
const CSS = (v) => getComputedStyle(document.documentElement).getPropertyValue(v).trim();

// ---------- Stacked area: sentimiento (pos/neu/neg) ----------
function StackedSentiment({ data, height = 230 }) {
  const W = 720, H = height, padL = 8, padR = 8, padT = 14, padB = 22;
  const n = data.length;
  const innerW = W - padL - padR, innerH = H - padT - padB;
  // Math.max(1, ...) evita división por cero cuando el historial está vacío.
  const max = Math.max(1, ...data.map(d => d.pos + d.neu + d.neg)) * 1.05;
  const x = (i) => padL + (i / Math.max(1, n - 1)) * innerW;
  const y = (v) => padT + innerH - (v / max) * innerH;

  // build stacked layers bottom→top: neg, neu, pos
  const layers = [
    { key: "neg", color: "var(--neg)", fill: "rgba(224,83,61,.55)" },
    { key: "neu", color: "var(--neu)", fill: "rgba(126,141,176,.38)" },
    { key: "pos", color: "var(--brand)", fill: "rgba(20,196,106,.45)" },
  ];
  const cum = data.map(() => 0);
  const paths = layers.map(layer => {
    const top = data.map((d, i) => { const base = cum[i]; cum[i] += d[layer.key]; return { i, lo: base, hi: cum[i] }; });
    const up = top.map(p => `${x(p.i)},${y(p.hi)}`).join(" L ");
    const down = [...top].reverse().map(p => `${x(p.i)},${y(p.lo)}`).join(" L ");
    return { d: `M ${up} L ${down} Z`, ...layer };
  });

  return (
    <svg viewBox={`0 0 ${W} ${H}`} width="100%" height={H} preserveAspectRatio="none" style={{ display: "block" }}>
      {[0.25, 0.5, 0.75, 1].map((g, i) => (
        <line key={i} x1={padL} x2={W - padR} y1={padT + innerH * (1 - g)} y2={padT + innerH * (1 - g)}
          stroke="rgba(160,180,220,.08)" strokeWidth="1" />
      ))}
      {paths.map((p, i) => <path key={i} d={p.d} fill={p.fill} stroke={p.color} strokeWidth="1.5" />)}
      {/* day ticks */}
      {[0, 9, 19, 29].map(i => (
        <text key={i} x={x(i)} y={H - 6} fill="var(--ice-faint)" fontSize="10" textAnchor={i === 0 ? "start" : i === 29 ? "end" : "middle"} fontFamily="var(--font-mono)">
          {i === 29 ? "hoy" : `-${29 - i}d`}
        </text>
      ))}
    </svg>
  );
}

// ---------- Gauge de contaminación (semicírculo, zonas) ----------
function Gauge({ value, size = 210 }) {
  const r = 86, cx = 110, cy = 110, sw = 16;
  const a0 = Math.PI, a1 = 0; // 180° → 0°
  const ang = a0 + (a1 - a0) * (value / 100);
  const polar = (a) => [cx + r * Math.cos(a), cy + r * Math.sin(a)];
  const arc = (from, to, color, op = 1) => {
    const [x1, y1] = polar(from), [x2, y2] = polar(to);
    const large = Math.abs(to - from) > Math.PI ? 1 : 0;
    return <path d={`M ${x1} ${y1} A ${r} ${r} 0 ${large} 1 ${x2} ${y2}`} stroke={color} strokeWidth={sw} fill="none" strokeLinecap="butt" opacity={op} />;
  };
  const seg = (frac) => a0 + (a1 - a0) * frac;
  const [nx, ny] = polar(ang);
  return (
    <svg viewBox="0 0 220 132" width={size} height={size * 0.6} style={{ display: "block", margin: "0 auto" }}>
      {arc(seg(0), seg(0.45), "var(--pos)")}
      {arc(seg(0.45), seg(0.7), "var(--gold)")}
      {arc(seg(0.7), seg(1), "var(--neg)")}
      {/* needle */}
      <line x1={cx} y1={cy} x2={nx} y2={ny} stroke="var(--white)" strokeWidth="3" strokeLinecap="round" />
      <circle cx={cx} cy={cy} r="7" fill="var(--white)" />
      <circle cx={cx} cy={cy} r="3" fill="var(--navy-bg)" />
    </svg>
  );
}

// ---------- Barras Share of Voice (horizontal) ----------
function SoVBars({ rows = [], t }) {
  if (!rows || rows.length === 0) return <div className="empty-hint">Sin datos de Share of Voice</div>;
  const max = Math.max(1, ...rows.map(r => r.sov));
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 11 }}>
      {rows.map((r, i) => (
        <div key={i} style={{ display: "flex", alignItems: "center", gap: 12 }}>
          <div style={{ width: 118, fontSize: 13, fontWeight: 600, color: r.note === "you" ? "var(--brand)" : "var(--ice)", textAlign: "right", flex: "none" }}>
            {r.name}{r.note === "you" ? " ●" : ""}
          </div>
          <div style={{ flex: 1, height: 22, background: "rgba(160,180,220,.08)", borderRadius: 6, overflow: "hidden" }}>
            <div style={{ width: `${(r.sov / max) * 100}%`, height: "100%", background: r.color, borderRadius: 6, transition: "width .6s cubic-bezier(.22,1,.36,1)" }}></div>
          </div>
          <div style={{ width: 42, fontFamily: "var(--font-mono)", fontSize: 13, fontWeight: 600, color: "var(--ice)", textAlign: "right" }}>{r.sov}%</div>
        </div>
      ))}
    </div>
  );
}

// ---------- Sparkline (alertas) ----------
function Sparkline({ data = [], color = "var(--neg)", w = 96, h = 30 }) {
  if (!data || data.length === 0) return null;
  const max = Math.max(1, ...data), min = Math.min(0, ...data);
  const x = (i) => (i / Math.max(1, data.length - 1)) * w;
  const y = (v) => h - ((v - min) / (max - min || 1)) * (h - 4) - 2;
  const d = data.map((v, i) => `${i === 0 ? "M" : "L"} ${x(i).toFixed(1)} ${y(v).toFixed(1)}`).join(" ");
  const area = `${d} L ${w} ${h} L 0 ${h} Z`;
  return (
    <svg width={w} height={h} viewBox={`0 0 ${w} ${h}`}>
      <path d={area} fill={color} opacity="0.14" />
      <path d={d} fill="none" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
      <circle cx={x(data.length - 1)} cy={y(data[data.length - 1])} r="3" fill={color} />
    </svg>
  );
}

// ---------- Narrative track (mini area por tema) ----------
function NarrTrack({ vol, tone }) {
  const w = 100, h = 38;
  const color = tone === "neg" ? "var(--neg)" : tone === "pos" ? "var(--brand)" : "var(--neu)";
  const max = Math.max(1, ...vol); // evita división por cero
  const x = (i) => (i / (vol.length - 1)) * w;
  const y = (v) => h - (v / max) * (h - 6) - 3;
  const line = vol.map((v, i) => `${i === 0 ? "M" : "L"} ${x(i).toFixed(1)} ${y(v).toFixed(1)}`).join(" ");
  return (
    <svg width="100%" height={h} viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none">
      <path d={`${line} L ${w} ${h} L 0 ${h} Z`} fill={color} opacity="0.16" />
      <path d={line} fill="none" stroke={color} strokeWidth="2" vectorEffect="non-scaling-stroke" />
    </svg>
  );
}

// ---------- heat color helper (verde→ámbar→rojo) ----------
function heatColor(v) {
  // 0 verde, 50 ámbar, 100 rojo
  const stops = [
    [0,   [20, 196, 106]],
    [45,  [224, 161, 6]],
    [100, [200, 65, 47]],
  ];
  let lo = stops[0], hi = stops[stops.length - 1];
  for (let i = 0; i < stops.length - 1; i++) {
    if (v >= stops[i][0] && v <= stops[i + 1][0]) { lo = stops[i]; hi = stops[i + 1]; break; }
  }
  const t = (v - lo[0]) / (hi[0] - lo[0] || 1);
  const c = lo[1].map((ch, i) => Math.round(ch + (hi[1][i] - ch) * t));
  return `rgb(${c[0]},${c[1]},${c[2]})`;
}

function formatNum(num) {
  if (num >= 1000000) return (num / 1000000).toFixed(1).replace(/\.0$/, "") + "M";
  if (num >= 1000) return (num / 1000).toFixed(0) + "k";
  return num.toString();
}

// ---------- Barras de Descargas Apiladas ----------
function DownloadsBars({ rows = [], t }) {
  if (!rows || rows.length === 0) return <div className="empty-hint">Sin datos de descargas</div>;
  
  const data = rows.map(r => {
    const play = r.downloads?.playstore || 0;
    const app = r.downloads?.appstore || 0;
    const total = play + app;
    return {
      name: r.name,
      note: r.note,
      play,
      app,
      total
    };
  }).sort((a, b) => b.total - a.total);

  const max = Math.max(1, ...data.map(d => d.total));

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 11 }}>
      {/* Legend */}
      <div style={{ display: "flex", gap: 16, justifyContent: "flex-end", marginBottom: 4, fontSize: 11, color: "var(--ice-faint)" }}>
        <span style={{ display: "flex", alignItems: "center", gap: 6 }}>
          <span style={{ width: 10, height: 10, borderRadius: 2, background: "var(--brand)" }}></span>
          Google Play Store
        </span>
        <span style={{ display: "flex", alignItems: "center", gap: 6 }}>
          <span style={{ width: 10, height: 10, borderRadius: 2, background: "var(--blue)" }}></span>
          Apple App Store
        </span>
      </div>

      {data.map((r, i) => {
        const pctPlay = (r.play / max) * 100;
        const pctApp = (r.app / max) * 100;
        
        return (
          <div key={i} style={{ display: "flex", alignItems: "center", gap: 12 }}>
            <div style={{ width: 118, fontSize: 13, fontWeight: 600, color: r.note === "you" ? "var(--brand)" : "var(--ice)", textAlign: "right", flex: "none" }}>
              {r.name}{r.note === "you" ? " ●" : ""}
            </div>
            
            <div style={{ flex: 1, height: 22, background: "rgba(160,180,220,.08)", borderRadius: 6, overflow: "hidden", display: "flex" }}>
              <div 
                style={{ 
                  width: `${pctPlay}%`, 
                  height: "100%", 
                  background: "var(--brand)", 
                  transition: "width .6s cubic-bezier(.22,1,.36,1)" 
                }}
                title={`Google Play: ${r.play.toLocaleString()}`}
              ></div>
              <div 
                style={{ 
                  width: `${pctApp}%`, 
                  height: "100%", 
                  background: "var(--blue)", 
                  transition: "width .6s cubic-bezier(.22,1,.36,1)" 
                }}
                title={`App Store: ${r.app.toLocaleString()}`}
              ></div>
            </div>
            
            <div style={{ width: 50, fontFamily: "var(--font-mono)", fontSize: 12, fontWeight: 600, color: "var(--ice)", textAlign: "right" }} title={`Total: ${r.total.toLocaleString()}`}>
              {formatNum(r.total)}
            </div>
          </div>
        );
      })}
    </div>
  );
}

Object.assign(window, { StackedSentiment, Gauge, SoVBars, Sparkline, NarrTrack, heatColor, DownloadsBars });
