// Shared primitive components for the SEIS+ Internals dashboard.

const fmtMoney = (n, dp = 4) => {
  const sign = n < 0 ? "-" : "";
  const v = Math.abs(n).toFixed(dp);
  const [int, dec] = v.split(".");
  const intGrouped = int.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
  return { sign, int: intGrouped, dec };
};

const fmtInt = (n) => n.toLocaleString("en-US");

function MoneyBig({ value, of, prefix = "$", small }) {
  const { sign, int, dec } = fmtMoney(value);
  return (
    <div className={`bignum num ${small ? "small" : ""}`} style={small ? { fontSize: 36 } : null}>
      <span style={{ color: "var(--muted)", fontSize: "0.42em", verticalAlign: "top", marginRight: 4 }}>{prefix}</span>
      {sign}{int}<span className="cents">.{dec}</span>
      {of != null && <span className="of">/ ${fmtMoney(of).int}.{fmtMoney(of).dec}</span>}
    </div>
  );
}

function Bar({ value, max, tone = "default", thin }) {
  const pct = Math.min(100, Math.max(0, (value / max) * 100));
  const cls = tone === "warn" ? "warn" : tone === "danger" ? "danger" : "";
  return (
    <div className={`bar ${cls} ${thin ? "thin" : ""}`}>
      <span style={{ width: `${pct}%` }} />
    </div>
  );
}

function Pill({ children, live, dotColor }) {
  return (
    <span className={`pill ${live ? "live" : ""}`}>
      {dotColor === "pulse" && <span className="dot pulse" />}
      {dotColor && dotColor !== "pulse" && <span className="dot" style={{ background: dotColor }} />}
      {children}
    </span>
  );
}

function PanelHead({ idx, title, right, live }) {
  return (
    <div className="panel-head">
      <span className="idx">{idx}</span>
      <span className="title row gap-8" style={{ alignItems: "center" }}>
        {title}
        {live && <Pill live dotColor="pulse">LIVE</Pill>}
      </span>
      <span className="right">{right}</span>
    </div>
  );
}

function Panel({ idx, title, right, live, children, style }) {
  return (
    <div className="panel" style={style}>
      <PanelHead idx={idx} title={title} right={right} live={live} />
      <div className="panel-body">{children}</div>
    </div>
  );
}

function SectionHead({ sigil, num, title, sub, right }) {
  return (
    <div className="section-head">
      <span className="sigil">§</span>
      <h2>
        <span style={{ color: "var(--muted)", marginRight: 14 }}>{num}</span>
        {title}
        {sub && <small>— {sub}</small>}
      </h2>
      <span className="right">{right}</span>
    </div>
  );
}

// Sparkline using inline SVG.
function Sparkline({ data, height = 36, color = "var(--ink)", fill = false }) {
  const w = 100, h = 100;
  const max = Math.max(...data), min = Math.min(...data);
  const range = max - min || 1;
  const pts = data.map((v, i) => {
    const x = (i / (data.length - 1)) * w;
    const y = h - ((v - min) / range) * h;
    return [x, y];
  });
  const d = pts.map(([x, y], i) => `${i === 0 ? "M" : "L"}${x.toFixed(2)},${y.toFixed(2)}`).join(" ");
  const dFill = `${d} L ${w},${h} L 0,${h} Z`;
  return (
    <svg viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none" className="chart" style={{ height }}>
      {fill && <path d={dFill} fill={color} opacity="0.12" />}
      <path d={d} fill="none" stroke={color} strokeWidth="1.5" vectorEffect="non-scaling-stroke" />
    </svg>
  );
}

// Vertical bar chart for daily spend.
function BarsDaily({ data, height = 64, color = "var(--ink)" }) {
  const max = Math.max(...data, 1);
  return (
    <div style={{ display: "flex", alignItems: "flex-end", gap: 2, height }}>
      {data.map((v, i) => (
        <div key={i} style={{
          flex: 1,
          height: `${(v / max) * 100}%`,
          background: i === data.length - 1 ? "var(--accent)" : color,
          opacity: i === data.length - 1 ? 1 : 0.55,
        }} title={`${i+1}: $${v.toFixed(2)}`} />
      ))}
    </div>
  );
}

// Status dot
function StatusDot({ status }) {
  const map = {
    online:   { c: "var(--ok)" },
    focus:    { c: "var(--warn)" },
    away:     { c: "var(--muted)" },
    offline:  { c: "transparent", border: true },
    running:  { c: "var(--ok)" },
    "spinning-up": { c: "var(--warn)" },
    stopped:  { c: "var(--muted)" },
  };
  const { c, border } = map[status] || { c: "var(--muted)" };
  return (
    <span style={{
      display: "inline-block", width: 8, height: 8, borderRadius: "50%",
      background: c, border: border ? "1px solid var(--ink)" : "0",
      verticalAlign: "middle", marginRight: 6,
    }} />
  );
}

window.SEIS_PRIM = { fmtMoney, fmtInt, MoneyBig, Bar, Pill, Panel, PanelHead, SectionHead, Sparkline, BarsDaily, StatusDot };
