// ui.jsx — shared primitives
const { useState } = React;

function Logo({ size = 22, withWord = true }) {
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 9 }}>
      {/* Kaval mark (201x278 source — height-driven) */}
      <img src="/kaval-logo.svg" alt="" style={{ display: "block", height: size * 1.18, width: "auto", flexShrink: 0 }} />
      {withWord && (
        <span style={{ fontWeight: 600, fontSize: size * 0.78, letterSpacing: "-0.02em", color: "var(--text)" }}>
          Kaval
        </span>
      )}
    </div>
  );
}

function Button({ children, variant = "primary", size = "md", icon, iconRight, full, ...p }) {
  const base = {
    display: "inline-flex", alignItems: "center", justifyContent: "center", gap: 8,
    fontWeight: 540, fontFamily: "var(--font-sans)", borderRadius: "var(--radius-sm)",
    border: "1px solid transparent", whiteSpace: "nowrap", transition: "all .14s ease",
    width: full ? "100%" : "auto", letterSpacing: "-0.01em",
  };
  const sizes = {
    sm: { fontSize: 13, padding: "6px 11px", height: 32 },
    md: { fontSize: 14, padding: "9px 16px", height: 40 },
    lg: { fontSize: 15.5, padding: "12px 22px", height: 48 },
  };
  const variants = {
    primary: { background: "var(--accent)", color: "var(--accent-fg)", boxShadow: "var(--shadow-sm)" },
    secondary: { background: "var(--surface)", color: "var(--text)", borderColor: "var(--border-2)", boxShadow: "var(--shadow-xs)" },
    ghost: { background: "transparent", color: "var(--text-2)" },
    subtle: { background: "var(--surface-3)", color: "var(--text)", borderColor: "var(--border)" },
    danger: { background: "var(--surface)", color: "var(--high-text)", borderColor: "var(--high-border)" },
  };
  const [h, setH] = useState(false);
  const hov = {
    primary: { background: "var(--accent-hover)" },
    secondary: { borderColor: "var(--border-strong)", background: "var(--surface-2)" },
    ghost: { background: "var(--surface-3)", color: "var(--text)" },
    subtle: { background: "var(--surface-2)", borderColor: "var(--border-2)" },
    danger: { background: "var(--high-subtle)" },
  };
  return (
    <button {...p}
      onMouseEnter={() => setH(true)} onMouseLeave={() => setH(false)}
      style={{ ...base, ...sizes[size], ...variants[variant], ...(h ? hov[variant] : {}), ...(p.disabled ? { opacity: 0.5, pointerEvents: "none" } : {}), ...(p.style || {}) }}>
      {icon}{children}{iconRight}
    </button>
  );
}

function Pill({ children, tone = "neutral", icon, dot, style }) {
  const tones = {
    neutral: { bg: "var(--surface-3)", fg: "var(--text-2)", bd: "var(--border)" },
    accent:  { bg: "var(--accent-subtle)", fg: "var(--accent-text)", bd: "var(--accent-border)" },
    high:    { bg: "var(--high-subtle)", fg: "var(--high-text)", bd: "var(--high-border)" },
    med:     { bg: "var(--med-subtle)", fg: "var(--med-text)", bd: "var(--med-border)" },
    low:     { bg: "var(--low-subtle)", fg: "var(--low-text)", bd: "var(--low-border)" },
    pass:    { bg: "var(--pass-subtle)", fg: "var(--pass-text)", bd: "var(--pass-border)" },
  };
  const t = tones[tone] || tones.neutral;
  return (
    <span style={{ display: "inline-flex", alignItems: "center", gap: 5, fontSize: 11.5, fontWeight: 560,
      padding: "2.5px 8px", borderRadius: 999, background: t.bg, color: t.fg, border: `1px solid ${t.bd}`,
      letterSpacing: "0.01em", lineHeight: 1.4, whiteSpace: "nowrap", ...style }}>
      {dot && <span style={{ width: 6, height: 6, borderRadius: 999, background: t.fg }} />}
      {icon}{children}
    </span>
  );
}

function SeverityTag({ sev, size = "md" }) {
  const fallback = {
    high: { label: "High", color: "var(--high)", text: "var(--high-text)", bg: "var(--high-subtle)", border: "var(--high-border)" },
    medium: { label: "Medium", color: "var(--med)", text: "var(--med-text)", bg: "var(--med-subtle)", border: "var(--med-border)" },
    low: { label: "Low", color: "var(--low)", text: "var(--low-text)", bg: "var(--low-subtle)", border: "var(--low-border)" },
  };
  const m = fallback[sev] || fallback.low;
  const px = size === "sm" ? { fs: 10.5, pad: "2px 7px 2px 6px", dot: 6 } : { fs: 12, pad: "3px 10px 3px 8px", dot: 7 };
  return (
    <span style={{ display: "inline-flex", alignItems: "center", gap: 6, fontSize: px.fs, fontWeight: 600,
      textTransform: "uppercase", letterSpacing: "0.04em", padding: px.pad, borderRadius: 6,
      background: m.bg, color: m.text, border: `1px solid ${m.border}` }}>
      <span style={{ width: px.dot, height: px.dot, borderRadius: 2, background: m.color }} />
      {m.label}
    </span>
  );
}

function TypeTag({ type }) {
  const fallback = {
    validator: { label: "Validator", icon: "shieldCheck" },
    dependency: { label: "Dependency", icon: "func" },
    database: { label: "Database", icon: "database" },
    schema: { label: "Schema", icon: "layers" },
    contract: { label: "Contract", icon: "doc" },
  };
  const m = fallback[type] || { label: type, icon: "doc" };
  return (
    <span style={{ display: "inline-flex", alignItems: "center", gap: 5, fontSize: 11.5, fontWeight: 540,
      color: "var(--text-2)" }}>
      {window.Icon[m.icon]({ s: 13 })}
      {m.label}
    </span>
  );
}

function Card({ children, pad, hover, style, ...p }) {
  const [h, setH] = useState(false);
  return (
    <div {...p}
      onMouseEnter={() => hover && setH(true)} onMouseLeave={() => hover && setH(false)}
      style={{ background: "var(--surface)", border: "1px solid var(--border)", borderRadius: "var(--radius)",
        boxShadow: h ? "var(--shadow)" : "var(--shadow-xs)", transition: "box-shadow .16s ease, border-color .16s ease",
        ...(h ? { borderColor: "var(--border-2)" } : {}),
        padding: pad === undefined ? "var(--card-pad)" : pad, ...style }}>
      {children}
    </div>
  );
}

function Avatar({ initials, size = 28, hue = 256 }) {
  return (
    <div style={{ width: size, height: size, borderRadius: 7, flexShrink: 0,
      background: `oklch(0.93 0.04 ${hue})`, color: `oklch(0.42 0.13 ${hue})`,
      display: "flex", alignItems: "center", justifyContent: "center",
      fontSize: size * 0.36, fontWeight: 600, letterSpacing: "0.02em",
      border: `1px solid oklch(0.86 0.06 ${hue})` }}>
      {initials}
    </div>
  );
}

function ShaChip({ sha, label, tone = "neutral", repo }) {
  const tones = {
    neutral: { bg: "var(--surface-3)", fg: "var(--text-2)", bd: "var(--border)" },
    base: { bg: "var(--surface-3)", fg: "var(--text-2)", bd: "var(--border)" },
    head: { bg: "var(--accent-subtle)", fg: "var(--accent-text)", bd: "var(--accent-border)" },
  };
  const t = tones[tone];
  // With a repo, the chip opens the commit on GitHub in a new tab. Private
  // repos resolve only for viewers with access — the link is still correct.
  const linked = Boolean(repo && sha);
  const box = { display: "inline-flex", alignItems: "center", gap: 6, padding: "2px 8px", borderRadius: 6,
    background: t.bg, border: `1px solid ${t.bd}`, ...(linked ? { textDecoration: "none", cursor: "pointer" } : {}) };
  const inner = (
    <>
      {label && <span style={{ fontSize: 10, fontWeight: 600, textTransform: "uppercase", letterSpacing: "0.06em", color: t.fg, opacity: 0.7 }}>{label}</span>}
      <span className="mono-sha" style={{ fontSize: 12, color: t.fg, fontWeight: 500, ...(linked ? { textDecorationLine: "underline", textDecorationStyle: "dotted", textUnderlineOffset: 2 } : {}) }}>{sha}</span>
    </>
  );
  if (linked) {
    return (
      <a href={`https://github.com/${repo}/commit/${sha}`} target="_blank" rel="noreferrer noopener" title={`Open ${sha} on GitHub`} style={box}>{inner}</a>
    );
  }
  return <span style={box}>{inner}</span>;
}

function FitBadge({ fit, size = "md" }) {
  const m = {
    high: { tone: "pass", label: "High fit" },
    medium: { tone: "med", label: "Medium fit" },
    low: { tone: "low", label: "Low fit" },
  }[fit];
  return <Pill tone={m.tone} dot>{m.label}</Pill>;
}

function Segmented({ options, value, onChange, size = "md" }) {
  const pad = size === "sm" ? "5px 10px" : "7px 13px";
  const fs = size === "sm" ? 12.5 : 13.5;
  return (
    <div style={{ display: "inline-flex", padding: 3, gap: 2, background: "var(--surface-3)",
      border: "1px solid var(--border)", borderRadius: 8 }}>
      {options.map((o) => {
        const active = o.value === value;
        return (
          <button key={o.value} onClick={() => onChange(o.value)}
            style={{ display: "inline-flex", alignItems: "center", gap: 6, padding: pad, fontSize: fs,
              fontWeight: 540, border: "none", borderRadius: 6, cursor: "pointer", letterSpacing: "-0.01em",
              background: active ? "var(--surface)" : "transparent",
              color: active ? "var(--text)" : "var(--text-3)",
              boxShadow: active ? "var(--shadow-xs)" : "none", transition: "all .13s ease" }}>
            {o.icon}{o.label}{o.count != null && <span style={{ fontSize: 11, opacity: 0.6 }}>{o.count}</span>}
          </button>
        );
      })}
    </div>
  );
}

function Bar({ pct, color = "var(--accent)", h = 6, track = "var(--surface-3)", anim = true }) {
  return (
    <div style={{ height: h, borderRadius: 999, background: track, overflow: "hidden", width: "100%" }}>
      <div style={{ height: "100%", width: `${pct}%`, background: color, borderRadius: 999,
        animation: anim ? "barfill .9s cubic-bezier(0.22,1,0.36,1)" : "none" }} />
    </div>
  );
}

Object.assign(window, { Logo, Button, Pill, SeverityTag, TypeTag, Card, Avatar, ShaChip, FitBadge, Segmented, Bar });
