// Small UI atoms — badges, sparklines, gradient rings, etc.
// Linear/Vercel-inspired: monochromatic, single-accent, subtle borders.

const { useMemo, useEffect, useState, useRef } = React;

// ─── Grade badge ───────────────────────────────────────────────
function Grade({ g, size = "sm" }) {
  const palette = {
    S: { fg: "var(--grade-s)", bg: "var(--grade-s-bg)" },
    A: { fg: "var(--grade-a)", bg: "var(--grade-a-bg)" },
    B: { fg: "var(--grade-b)", bg: "var(--grade-b-bg)" },
    C: { fg: "var(--grade-c)", bg: "var(--grade-c-bg)" },
  };
  const p = palette[g] || palette.C;
  return (
    <span className={`grade-badge grade-${size}`} style={{ color: p.fg, background: p.bg, borderColor: p.fg + "55" }}>
      {g}
    </span>
  );
}

// ─── Sparkline (svg, line + soft fill) ─────────────────────────
function Sparkline({ data, width = 88, height = 28, stroke = "var(--accent)", fill = "var(--accent-soft)" }) {
  const path = useMemo(() => {
    if (!data || data.length === 0) return { line: "", area: "" };
    const min = Math.min(...data);
    const max = Math.max(...data);
    const range = max - min || 1;
    const stepX = width / (data.length - 1);
    const pts = data.map((v, i) => [i * stepX, height - ((v - min) / range) * (height - 4) - 2]);
    const line = pts.map((p, i) => (i === 0 ? `M${p[0]},${p[1]}` : `L${p[0]},${p[1]}`)).join(" ");
    const area = `${line} L${width},${height} L0,${height} Z`;
    return { line, area };
  }, [data, width, height]);
  return (
    <svg width={width} height={height} style={{ display: "block", overflow: "visible" }}>
      <path d={path.area} fill={fill} stroke="none" />
      <path d={path.line} fill="none" stroke={stroke} strokeWidth="1.5" strokeLinejoin="round" strokeLinecap="round" />
    </svg>
  );
}

// ─── Outcome pill ──────────────────────────────────────────────
function Outcome({ value, revenue }) {
  const map = {
    success:  { label: "성공", fg: "var(--success)", bg: "color-mix(in oklch, var(--success) 14%, transparent)" },
    fail:     { label: "실패", fg: "var(--danger)",  bg: "color-mix(in oklch, var(--danger) 14%, transparent)" },
    pending:  { label: "대기", fg: "var(--text-tertiary)", bg: "var(--bg-overlay)" },
    sourcing: { label: "소싱", fg: "var(--warning)", bg: "color-mix(in oklch, var(--warning) 14%, transparent)" },
  };
  if (!value) return <span className="outcome-pill empty">—</span>;
  const m = map[value] || map.pending;
  return (
    <span className="outcome-pill" style={{ color: m.fg, background: m.bg }}>
      <span className="dot" style={{ background: m.fg }}></span>
      {m.label}
      {revenue ? <span className="rev">{(revenue / 1_000_000).toFixed(1)}M</span> : null}
    </span>
  );
}

// ─── Trend arrow (▲ / ▼ / —) ───────────────────────────────────
function TrendArrow({ dir, value }) {
  const isOk = (dir === "up" && (value || "").toString().indexOf("-") !== 0)
            || (dir === "down" && (value || "").toString().indexOf("-") === 0);
  const sym = dir === "up" ? "↑" : dir === "down" ? "↓" : "→";
  return (
    <span className="trend" data-ok={isOk ? "1" : "0"}>
      {sym} {value}
    </span>
  );
}

// ─── Bar (mini) ────────────────────────────────────────────────
function Bar({ pct, max = 100, color = "var(--accent)" }) {
  const w = Math.max(0, Math.min(100, (pct / max) * 100));
  return (
    <div className="bar-track">
      <div className="bar-fill" style={{ width: `${w}%`, background: color }}></div>
    </div>
  );
}

// ─── Section header (h2) ───────────────────────────────────────
function SectionHeader({ icon, title, sub, right }) {
  return (
    <div className="sec-head">
      <h2>
        {icon ? <span className="sec-icon">{icon}</span> : null}
        <span>{title}</span>
        {sub ? <span className="sec-sub">{sub}</span> : null}
      </h2>
      {right ? <div className="sec-right">{right}</div> : null}
    </div>
  );
}

// ─── Live clock ────────────────────────────────────────────────
function LiveClock() {
  const [t, setT] = useState(() => new Date());
  useEffect(() => {
    const id = setInterval(() => setT(new Date()), 1000);
    return () => clearInterval(id);
  }, []);
  const h = String(t.getHours()).padStart(2, "0");
  const m = String(t.getMinutes()).padStart(2, "0");
  const s = String(t.getSeconds()).padStart(2, "0");
  return <span className="clock-mono">{h}:{m}<span className="sep">:</span>{s}</span>;
}

// ─── Connection indicator (pulse) ──────────────────────────────
function ConnDot({ ok = true }) {
  return (
    <span className="conn-wrap" title={ok ? "연결됨" : "연결 끊김"}>
      <span className={"conn-dot " + (ok ? "ok" : "off")}></span>
      <span className="conn-label">{ok ? "Live" : "Offline"}</span>
    </span>
  );
}

// ─── Keyboard hint ─────────────────────────────────────────────
function Kbd({ children }) {
  return <kbd className="kbd">{children}</kbd>;
}

// ─── Spinner ───────────────────────────────────────────────────
function Spinner({ size = 14 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" className="spin">
      <circle cx="12" cy="12" r="9" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeDasharray="40 60" />
    </svg>
  );
}

Object.assign(window, { Grade, Sparkline, Outcome, TrendArrow, Bar, SectionHeader, LiveClock, ConnDot, Kbd, Spinner });
