/* Shared components, icons, helpers */

/* ---------- tiny icon set (stroke) ---------- */
const I = {
  refresh: "M13.5 7a5.5 5.5 0 1 0-1.6 3.9M13.5 7V3.5M13.5 7H10",
  spark: "M8 1.5l1.6 4L14 7l-4.4 1.5L8 13l-1.6-4.5L2 7l4.4-1.5L8 1.5z",
  play: "M5 3.5l8 4.5-8 4.5z",
  edit: "M11 2.5l2.5 2.5M2.5 11L10 3.5l2.5 2.5L5 13.5l-3 .5z",
  x: "M3.5 3.5l9 9M12.5 3.5l-9 9",
  rocket: "M8 1.5c2.2 1.2 3.5 3.6 3.5 6.2 0 1.3-.3 2.4-.8 3.3H5.3c-.5-.9-.8-2-.8-3.3 0-2.6 1.3-5 3.5-6.2zM8 6.6a1.1 1.1 0 1 0 0 2.2 1.1 1.1 0 0 0 0-2.2zM4.5 11l-2 2.5L5 13M11.5 11l2 2.5L11 13",
  check: "M3 8.2l3.2 3.3L13 4.5",
  lock: "M4.5 7V5.2a3.5 3.5 0 0 1 7 0V7M3.5 7h9v6.5h-9z",
  copy: "M5.5 5.5V3.5h8v8h-2M2.5 5.5h8v8h-8z",
  plus: "M8 3v10M3 8h10",
  ext: "M6 3.5H3.5v9h9V10M9 3.5h3.5V7M12.5 3.5L7 9",
  filter: "M2.5 4h11M4.5 8h7M6.5 12h3",
  grid: "M3 3h4v4H3zM9 3h4v4H9zM3 9h4v4H3zM9 9h4v4H9z",
  arrowUp: "M8 12.5V3.5M4 7l4-3.5L12 7",
  arrowDown: "M8 3.5v9M4 9l4 3.5L12 9",
  warn: "M8 2l6.5 11.5h-13zM8 6.5v3.5M8 11.8v.1",
};
function Ico({ d, s = 16, w = 1.6, fill, style, cls }) {
  return (
    <svg className={cls} width={s} height={s} viewBox="0 0 16 16" fill="none" style={style}>
      <path d={d} stroke={fill ? "none" : "currentColor"} fill={fill || "none"} strokeWidth={w} strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
}

/* ---------- ADORE logo unit ---------- */
function LogoUnit() {
  return (
    <svg className="logo-unit" viewBox="0 0 40 40" fill="none">
      <path d="M3 27 Q20 14 37 27" stroke="var(--acc)" strokeWidth="2" fill="none" strokeLinecap="round" opacity="0.85" />
      <rect x="11" y="19" width="18" height="11" rx="1.5" stroke="var(--t1)" strokeWidth="1.8" />
      <path d="M9 19.5 L20 13 L31 19.5" stroke="var(--t1)" strokeWidth="1.8" strokeLinejoin="round" fill="none" />
      <line x1="20" y1="24" x2="20" y2="30" stroke="var(--t2)" strokeWidth="1.4" />
    </svg>
  );
}

/* ---------- status vocabulary ---------- */
function statusMeta(key) {
  switch (key) {
    case "queued":         return { label: "Queued", cls: "neutral" };
    case "generating":     return { label: "Generating", cls: "info gen" };
    case "ready":          return { label: "Ready (paused)", cls: "neutral" };
    case "paused":         return { label: "Paused", cls: "warn" };
    case "active":         return { label: "Active", cls: "good" };
    case "fatigued":       return { label: "Fatigued", cls: "warn" };
    case "underperformer": return { label: "Underperformer", cls: "bad" };
    case "gathering":      return { label: "Data gathering", cls: "info" };
    default:               return { label: key, cls: "neutral" };
  }
}
function Badge({ status }) {
  const m = statusMeta(status);
  return <span className={"badge " + m.cls}><span className="bd"></span>{m.label}</span>;
}

/* ---------- model → color hue for placeholder washes ---------- */
const MODEL_HUE = {
  sigB: 210, horizon: 168, crema: 32, horizonLine: 250, client217: 86, example: 320,
};
function modelWash(modelKey) {
  const h = MODEL_HUE[modelKey] ?? 210;
  return `radial-gradient(130% 110% at 25% 15%, oklch(0.9 0.06 ${h} / 0.85), transparent 60%),
          radial-gradient(120% 120% at 90% 100%, oklch(0.85 0.05 ${(h + 40) % 360} / 0.75), transparent 55%),
          linear-gradient(160deg, #f4f0e7, #ece6da)`;
}

/* ---------- placeholder media tile ---------- */
function MediaTile({ c, ratio = "9 / 16", children }) {
  const hasAsset = c.assetUrl && /^https?:/.test(c.assetUrl);
  return (
    <div className="media" style={{ aspectRatio: ratio }}>
      {hasAsset ? (
        c.isVideo
          ? <video src={c.assetUrl} muted loop playsInline preload="metadata" style={{ width: "100%", height: "100%", objectFit: "cover" }} />
          : <img src={c.assetUrl} loading="lazy" alt="" style={{ width: "100%", height: "100%", objectFit: "cover" }} />
      ) : (
        <>
          <div className="ph-grad" style={{ background: modelWash(c.modelKey) }}></div>
          <div className="ph"></div>
          <div className="ph-label">{c.isVideo ? "▶ " : "▣ "}{c.scene}</div>
        </>
      )}
      {c.isVideo && !hasAsset && <div className="play"><Ico d={I.play} s={13} fill="#fff" /></div>}
      {children}
    </div>
  );
}

/* ---------- formatters ---------- */
const fmt = {
  money: (n) => n == null ? "—" : "$" + Math.round(n).toLocaleString(),
  money2: (n) => n == null ? "—" : "$" + n.toLocaleString(undefined, { minimumFractionDigits: 0 }),
  cpl: (n) => n == null ? "—" : "$" + Math.round(n),
  int: (n) => n == null ? "—" : Math.round(n).toLocaleString(),
  pct: (n) => n == null ? "—" : n.toFixed(2) + "%",
  dash: (v, f) => (v === 0 || v == null) ? "—" : (f ? f(v) : v),
};

/* ---------- mini sparkline ---------- */
function Spark({ vals, w = 56, h = 20, color = "var(--acc)" }) {
  const max = Math.max(...vals), min = Math.min(...vals);
  const rng = max - min || 1;
  const pts = vals.map((v, i) => `${(i / (vals.length - 1)) * w},${h - ((v - min) / rng) * h}`).join(" ");
  return (
    <svg className="spark" width={w} height={h} viewBox={`0 0 ${w} ${h}`} fill="none">
      <polyline points={pts} stroke={color} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" opacity="0.9" />
    </svg>
  );
}

Object.assign(window, { I, Ico, LogoUnit, statusMeta, Badge, MediaTile, modelWash, MODEL_HUE, fmt, Spark });
