// Komponen UI bersama + util (beep scanner, CSV export, status badge).

// ---- Audio feedback (beep scanner) ----
let _audioCtx = null;
function beep(kind = "ok", enabled = true) {
  if (!enabled) return;
  try {
    _audioCtx = _audioCtx || new (window.AudioContext || window.webkitAudioContext)();
    const ctx = _audioCtx;
    const o = ctx.createOscillator();
    const g = ctx.createGain();
    o.connect(g); g.connect(ctx.destination);
    const now = ctx.currentTime;
    if (kind === "ok")      { o.type = "square";   o.frequency.value = 1480; }
    else if (kind === "done") { o.type = "sine";   o.frequency.setValueAtTime(880, now); o.frequency.setValueAtTime(1320, now + 0.09); }
    else                    { o.type = "sawtooth"; o.frequency.value = 220; } // error
    g.gain.setValueAtTime(0.0001, now);
    g.gain.exponentialRampToValueAtTime(0.18, now + 0.01);
    g.gain.exponentialRampToValueAtTime(0.0001, now + (kind === "done" ? 0.22 : 0.12));
    o.start(now); o.stop(now + (kind === "done" ? 0.24 : 0.14));
  } catch (e) {}
}

// ---- Status badge ----
function StatusBadge({ status, size = "md" }) {
  const map = {
    pending:   { label: "Menunggu QC", bg: "var(--warn-bg)", fg: "var(--warn-ink)", dot: "var(--warn)" },
    problem:   { label: "Menunggu QC", bg: "var(--warn-bg)", fg: "var(--warn-ink)", dot: "var(--warn)" },
    done:      { label: "Selesai",     bg: "var(--ok-bg)",   fg: "var(--ok-ink)",   dot: "var(--ok)" },
    completed: { label: "Selesai",     bg: "var(--ok-bg)",   fg: "var(--ok-ink)",   dot: "var(--ok)" },
    waiting:   { label: "Proses QC",   bg: "var(--pri-bg)",  fg: "var(--pri-ink2)", dot: "var(--pri)" },
    progress:  { label: "Proses QC",   bg: "var(--pri-bg)",  fg: "var(--pri-ink2)", dot: "var(--pri)" },
    shipped:   { label: "Dikirim",     bg: "var(--pri-bg)",  fg: "var(--pri-ink2)", dot: "var(--pri)" },
    canceled:  { label: "Dibatalkan",  bg: "var(--err-bg, #fef2f2)", fg: "var(--err-ink, #dc2626)", dot: "var(--err, #ef4444)" },
    returned:  { label: "Retur",       bg: "var(--warn-bg)", fg: "var(--warn-ink)", dot: "var(--warn)" },
  };
  const s = map[status] || map.pending;
  const pad = size === "sm" ? "3px 8px" : "5px 11px";
  const fs = size === "sm" ? 11 : 12.5;
  return (
    <span style={{
      display: "inline-flex", alignItems: "center", gap: 6, padding: pad,
      borderRadius: 999, background: s.bg, color: s.fg, fontSize: fs, fontWeight: 600,
      lineHeight: 1, whiteSpace: "nowrap",
    }}>
      <span style={{ width: 6, height: 6, borderRadius: 999, background: s.dot }} />
      {s.label}
    </span>
  );
}

function CourierTag({ courier, size = "md" }) {
  const c = window.QC_COURIERS[courier] || { label: courier, tone: "#64748b" };
  const fs = size === "sm" ? 11.5 : 12.5;
  return (
    <span style={{
      display: "inline-flex", alignItems: "center", gap: 6, fontSize: fs, fontWeight: 600,
      color: "var(--ink-2)",
    }}>
      <span style={{ width: 7, height: 7, borderRadius: 2, background: c.tone }} />
      {c.label}
    </span>
  );
}

// Mono chip untuk kode (resi, sku, barcode)
function Mono({ children, style }) {
  return <span style={{ fontFamily: "var(--mono)", letterSpacing: "-0.01em", ...style }}>{children}</span>;
}

// ---- Toast system ----
function useToasts() {
  const [toasts, setToasts] = React.useState([]);
  const push = React.useCallback((t) => {
    const id = Math.random().toString(36).slice(2);
    setToasts((xs) => [...xs, { id, ...t }]);
    setTimeout(() => setToasts((xs) => xs.filter((x) => x.id !== id)), t.duration || 2600);
  }, []);
  return [toasts, push];
}

function ToastStack({ toasts }) {
  const tone = {
    ok:   { bg: "#052e16", bd: "#16a34a", fg: "#dcfce7", icon: Icon.checkCircle },
    error:{ bg: "#450a0a", bd: "#ef4444", fg: "#fee2e2", icon: Icon.xCircle },
    warn: { bg: "#451a03", bd: "#f59e0b", fg: "#fef3c7", icon: Icon.alert },
  };
  return (
    <div style={{ position: "fixed", top: 76, left: "50%", transform: "translateX(-50%)",
      display: "flex", flexDirection: "column", gap: 8, zIndex: 200, alignItems: "center",
      pointerEvents: "none", width: "min(520px, 92vw)" }}>
      {toasts.map((t) => {
        const s = tone[t.kind] || tone.ok; const Ic = s.icon;
        return (
          <div key={t.id} className="qc-toast" style={{
            display: "flex", alignItems: "center", gap: 11, padding: "11px 16px",
            background: s.bg, border: `1px solid ${s.bd}`, color: s.fg, borderRadius: 10,
            boxShadow: "0 12px 32px rgba(0,0,0,.35)", fontSize: 14, fontWeight: 600,
            width: "100%", maxWidth: "100%",
          }}>
            <Ic size={20} stroke={s.bd} />
            <span style={{ flex: 1 }}>{t.msg}</span>
            {t.sub && <Mono style={{ fontSize: 12, opacity: 0.7, fontWeight: 500 }}>{t.sub}</Mono>}
          </div>
        );
      })}
    </div>
  );
}

// ---- CSV export ----
function ordersToCSV(orders) {
  const head = ["No Resi", "No Pesanan", "Customer", "Kurir", "Waktu QC", "Operator",
    "SKU", "Nama Produk", "Barcode", "Qty Pesanan", "Qty Scan", "Status Item"];
  const rows = [head];
  orders.forEach((o) => {
    const cour = (window.QC_COURIERS[o.courier] || {}).label || o.courier;
    o.items.forEach((it) => {
      rows.push([
        o.resi, o.order, o.customer, cour, o.doneTime ? `${o.doneTime} WIB` : "-", o.operator || "-",
        it.sku, it.name, it.barcode, it.qty, it.qty, "OK",
      ]);
    });
  });
  return rows.map((r) => r.map((c) => {
    const s = String(c ?? "");
    return /[",\n]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s;
  }).join(",")).join("\n");
}

function downloadCSV(filename, csv) {
  const blob = new Blob(["\ufeff" + csv], { type: "text/csv;charset=utf-8;" });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url; a.download = filename;
  document.body.appendChild(a); a.click(); a.remove();
  setTimeout(() => URL.revokeObjectURL(url), 1000);
}

Object.assign(window, { beep, StatusBadge, CourierTag, Mono, useToasts, ToastStack, ordersToCSV, downloadCSV });
