window.FB = window.FB || {};

FB.ReviewTab = function ReviewTab({ lang, user }) {
  const { useState, useEffect } = React;
  const t = FB.makeT(lang);
  const L = (zh, en) => (lang === "zh" ? zh : en);

  const [list, setList] = useState(null);
  const [sel, setSel] = useState(null);
  const [opts, setOpts] = useState([]);
  const [rows, setRows] = useState([]);          // 工作行
  const [inv, setInv] = useState({ no: "", total: "", supplier: "" });
  const [ai, setAi] = useState(null);
  const [aiState, setAiState] = useState("idle");
  const [zoom, setZoom] = useState(null);
  const [busy, setBusy] = useState(false);
  const [msg, setMsg] = useState(null);
  const [tab, setTab] = useState("pending");
  const [learnSupp, setLearnSupp] = useState(false);
  const [hist, setHist] = useState(null);
  // 盘点重复护栏 (2026-07-29): 货在盘点前已上架、审核在盘点后 → 盘点已把货数进实数,
  // 审核再写 inbound 会把同一批加两次。这里查「到货之后有没有盘过点」,有就提醒勾「不入库」。
  const [countedAfter, setCountedAfter] = useState(null);   // Set(item_code)

  function load() { FB.api.pendingReviews().then(setList); }
  useEffect(() => { load(); FB.api.itemOptions().then(setOpts); }, []);
  useEffect(() => {
    if (list && FB.setPageInfo) FB.setPageInfo(L("待审核", "Pending") + " " + list.length);
  }, [list, lang]);
  useEffect(() => { if (tab === "done" && !hist) FB.api.receivedHistory().then(setHist); }, [tab]);

  const itemMap = {};
  opts.forEach((o) => (itemMap[o.code] = o));
  const oname = (c) => {
    const o = itemMap[c];
    return o ? (lang === "zh" ? o.name_cn || o.code : o.name_en || o.code) : c;
  };

  // 打开单据：先用 PO 明细铺底
  function open(p) {
    setSel(p); setAi(null); setMsg(null);
    setCountedAfter(null);
    const codes = (p.items || []).map((r) => r.item_code).filter(Boolean);
    if (p.received_at && codes.length) {
      FB.sb.from("stock_movements").select("item_code")
        .eq("move_type", "stocktake_adjust").gt("moved_at", p.received_at).in("item_code", codes)
        .then(({ data }) => setCountedAfter(new Set((data || []).map((x) => x.item_code))));
    }
    const d = FB.draft.get("review_" + p.id, null);
    if (d && d.rows && d.rows.length) {
      setInv(d.inv); setRows(d.rows); setAiState(p.extracted ? "done" : "idle");
      if (p.extracted) setAi({ ...p.extracted, cached: true });
      return;
    }
    if (p.extracted && p.extracted.extracted) {
      setAiState("done"); setAi({ ...p.extracted, cached: true }); applyAI(p.extracted, p); return;
    }
    setAiState("idle");
    setInv({ no: p.invoice_no || "", total: p.invoice_total != null ? String(p.invoice_total) : "", supplier: p.supplier_name || "" });
    setRows((p.items || []).map((r) => ({
      raw_name: (r.items && r.items.name_cn) || r.item_code,
      item_code: r.item_code, qty: String(r.qty_received != null ? r.qty_received : r.qty_ordered),
      unit: r.unit, unit_price: "", amount: "", qty_ordered: r.qty_ordered,
      is_fee: false, skip_stock: false, matched_by: "po", learn: false,
    })));
  }

  function applyAI(r, po) {
    const ex = (r && r.extracted) || {};
    setInv({
      no: ex.invoice_no || po.invoice_no || "",
      total: ex.total != null ? String(ex.total) : (po.invoice_total != null ? String(po.invoice_total) : ""),
      supplier: po.supplier_name || ex.supplier_resolved || ex.supplier || "",
      raw: ex.supplier_raw || null,
      alias_known: !!ex.supplier_alias_known,
    });
    setLearnSupp(false);
    const ordMap = {};
    (po.items || []).forEach((x) => (ordMap[x.item_code] = Number(x.qty_ordered)));
    setRows((ex.lines || []).map((ln) => ({
      raw_name: ln.raw_name || "", item_code: ln.item_code || "",
      qty: ln.qty != null ? String(ln.qty) : "", unit: ln.unit || "",
      unit_price: ln.unit_price != null ? String(ln.unit_price) : "",
      amount: ln.amount != null ? String(ln.amount) : "",
      qty_ordered: ln.item_code ? ordMap[ln.item_code] : undefined,
      is_fee: !!ln.is_fee, skip_stock: !!ln.is_fee,
      matched_by: ln.matched_by, old_price: ln.old_price,
      item_unit: ln.item_unit, carton_size: ln.carton_size,
      pack: String(ln.suggest_pack != null ? ln.suggest_pack : 1),
      pack_text: ln.pack_text, unit_match: ln.unit_match, is_primary: ln.is_primary,
      primary_supplier: ln.primary_supplier, learn: false,
    })));
  }

  async function runExtract(force) {
    setAiState("running"); setMsg(null);
    const r = await FB.api.extractInvoice({ paths: sel.meta.files || [], po_id: sel.id, force: !!force });
    if (!r || r.error) { setAiState("error"); setAi({ error: (r && r.error) || "failed" }); return; }
    setAiState("done"); setAi(r); applyAI(r, sel);
    // 读完顺手补一次影子判定 (员工提交时没跑成的兜底)
    FB.api.autoReview({ po_id: sel.id }).catch(() => {});
  }

  const setR = (i, k, v) => setRows((x) => x.map((r, j) => (j === i ? { ...r, [k]: v } : r)));

  // 自动存草稿 — 刷新不丢
  useEffect(() => {
    if (sel && rows.length) FB.draft.set("review_" + sel.id, { rows, inv });
  }, [rows, inv, sel]);

  const sum = rows.reduce((a, r) => a + (Number(r.amount) || (Number(r.qty) || 0) * (Number(r.unit_price) || 0)), 0);
  const total = Number(inv.total) || 0;
  const diff = total > 0 ? sum - total : null;
  const unmapped = rows.filter((r) => !r.item_code && !r.is_fee && !r.skip_stock).length;

  async function approve() {
    setBusy(true);
    const r = await FB.api.approveReceiving({
      po_id: sel.id, supplier_name: inv.supplier || null,
      invoice_no: inv.no || null, invoice_total: inv.total ? Number(inv.total) : null,
      approved_by: user.name,
      lines: rows.map((x) => {
        const pk = Number(x.pack) > 0 ? Number(x.pack) : 1;
        const q = (Number(x.qty) || 0) * pk;
        const up = x.unit_price !== "" && Number(x.unit_price) > 0 ? Number(x.unit_price) / pk : null;
        return {
          item_code: x.item_code || null,
          qty: Math.round(q * 1000) / 1000,
          unit: x.item_unit || x.unit,
          unit_price: up != null ? Math.round(up * 10000) / 10000 : null,
          amount: x.amount !== "" ? Number(x.amount) : null,
          is_fee: x.is_fee, skip_stock: x.skip_stock,
        };
      }),
      save_aliases: rows.filter((x) => x.learn && x.item_code && x.raw_name)
        .map((x) => ({ alias: x.raw_name, item_code: x.item_code })),
      save_supplier_alias: learnSupp && inv.raw ? { alias: inv.raw } : null,
    });
    setBusy(false);
    if (r && r.ok) {
      FB.draft.clear("review_" + sel.id);
      setMsg({ ok: true, r });
      setTimeout(() => { setSel(null); setMsg(null); load(); }, 2600);
    } else setMsg({ ok: false, text: (r && r.error) || "failed" });
  }
  async function reject() {
    setBusy(true);
    await FB.api.approveReceiving({ po_id: sel.id, reject: true, note: L("退回重拍", "sent back") });
    FB.draft.clear("review_" + sel.id);
    setBusy(false); setSel(null); load();
  }

  // ── 列表 ──
  if (!sel) return (
    <div className="px-3 py-3 max-w-md mx-auto pb-20">
      <h1 className="text-[20px] font-semibold text-stone-900 px-1">{L("收货审核", "Receiving")}</h1>
      <div className="my-3">
        <FB.UI.Seg options={[["pending", L("待审核", "Pending")], ["done", L("已入库", "Done")]]} value={tab} onChange={setTab} />
      </div>

      {tab === "done" && (
        <>
          {!hist && <p className="text-sm text-stone-400 px-1">{t("loading")}</p>}
          {hist && hist.length === 0 && <div className="rounded-xl border border-stone-200 bg-white p-6 text-center text-sm text-stone-400">{L("还没有入库记录", "No records")}</div>}
          {(hist || []).map((p) => (
            <div key={p.id} className="rounded-xl border border-stone-200 bg-white p-3 mb-2">
              <div className="flex gap-3 items-center">
                {p.urls[0] && <img src={p.urls[0]} alt="" onClick={() => setZoom(p.urls[0])} className="w-12 h-12 rounded-xl object-cover bg-stone-100" />}
                <div className="flex-1 min-w-0">
                  <p className="text-[14px] font-medium text-stone-800 truncate">
                    {p.supplier_name}
                    {p.paid_by === "personal" && <span className="ml-1.5 text-[10px] px-1.5 py-0.5 rounded font-semibold" style={{ background: "#FDF2E8", color: "#C2540A" }}>{p.claim_status || L("垫付", "claim")}</span>}
                  </p>
                  <p className="text-[11px] text-stone-400">
                    {String(p.received_at || "").slice(0, 10)}{p.invoice_no ? " · #" + p.invoice_no : ""}
                  </p>
                </div>
                {p.invoice_total != null && <span className="text-[14px] font-medium tabular-nums text-stone-700">RM {Number(p.invoice_total).toFixed(2)}</span>}
              </div>
            </div>
          ))}
          {zoom && (
            <div onClick={() => setZoom(null)} className="fixed inset-0 z-50 flex items-center justify-center p-4" style={{ background: "rgba(0,0,0,.85)" }}>
              <img src={zoom} alt="" className="max-w-full max-h-full object-contain rounded-xl" />
            </div>
          )}
        </>
      )}

      {tab === "pending" && <>
      {!list && <p className="text-sm text-stone-400 px-1">{t("loading")}</p>}
      {list && list.length === 0 && (
        <div className="rounded-xl border border-stone-200 bg-white p-6 text-center text-sm text-stone-400">
          {L("没有待审核的", "Nothing pending")}
        </div>
      )}
      {(list || []).map((p) => (
        <button key={p.id} onClick={() => open(p)}
          className="w-full text-left rounded-xl border border-stone-200 bg-white p-3 mb-2 active:bg-stone-50">
          <div className="flex gap-3 items-center">
            {p.urls[0] && <img src={p.urls[0]} alt="" className="w-14 h-14 rounded-xl object-cover bg-stone-100" />}
            <div className="flex-1 min-w-0">
              <p className="text-[15px] font-medium text-stone-800 truncate">
                {p.supplier_name}
                {p.paid_by === "personal" && <span className="ml-1.5 text-[10px] px-1.5 py-0.5 rounded font-semibold" style={{ background: "#FDF2E8", color: "#C2540A" }}>{L("垫付", "claim")}</span>}
                {p.extracted && <span className="ml-1.5 text-[10px] px-1.5 py-0.5 rounded font-semibold" style={{ background: "#F0F6E8", color: "#4A7A1C" }}>✓ AI</span>}
                {FB.draft.get("review_" + p.id, null) && <span className="ml-1.5 text-[10px] px-1.5 py-0.5 rounded font-semibold bg-stone-100 text-stone-500">{L("有草稿", "draft")}</span>}
              </p>
              {/* 影子自动审核判定 (影子期只显示,不动手) */}
              {p.meta && p.meta.verdict && (
                <p className="text-[10px] mt-0.5 truncate font-semibold"
                  style={{ color: p.meta.verdict.auto ? "#4A7A1C" : "#C2540A" }}>
                  {p.meta.verdict.auto
                    ? L("影子:会自动过", "shadow: would auto-approve")
                    : L("影子:拦 · ", "shadow: hold · ") + (p.meta.verdict.reasons || []).slice(0, 2).join(" · ")}
                </p>
              )}
              <p className="text-[11px] text-stone-400 mt-0.5">
                {String(p.received_at || "").slice(0, 10)} · {p.items.length} {L("项", "items")} · {p.urls.length} {L("图", "img")}
              </p>
            </div>
            <span className="text-stone-300 text-lg">›</span>
          </div>
        </button>
      ))}
      </>}
    </div>
  );

  // ── 详情 ──
  return (
    <div className="px-3 py-3 max-w-md mx-auto pb-32">
      {/* sticky: 之前只是页顶一个小字链接, 滚下去就找不到退出口 */}
      <div className="sticky top-16 z-10 -mx-3 px-3 py-2 mb-1"
        style={{ background: "linear-gradient(to bottom,#FAFAF9 75%,transparent)" }}>
        <button onClick={() => setSel(null)}
          className="h-9 px-3 rounded-xl border border-stone-200 bg-white text-[13px] text-stone-600 active:bg-stone-100">
          ← {L("返回", "Back")}
        </button>
      </div>
      <h1 className="text-[18px] font-semibold text-stone-900">{sel.supplier_name}</h1>
      <p className="text-[11px] text-stone-400 mb-3">
        {String(sel.received_at || "").slice(0, 16).replace("T", " ")}
        {sel.meta.uploaded_by ? " · " + sel.meta.uploaded_by : ""}
      </p>

      {sel.urls.length > 0 && (
        <div className="flex gap-2 overflow-x-auto mb-3 pb-1">
          {sel.urls.map((u, i) => (
            <img key={i} src={u} alt="" onClick={() => setZoom(u)}
              className="h-32 rounded-xl object-cover border border-stone-200 shrink-0" />
          ))}
        </div>
      )}

      <p className="text-[10px] text-stone-400 mb-2">{L("边填边存，刷新不会丢", "auto-saved")}</p>
      <div className="flex gap-2 mb-3">
        <button onClick={() => runExtract(false)} disabled={aiState === "running" || !(sel.meta.files || []).length}
          className="flex-1 h-11 rounded-xl text-sm font-medium disabled:opacity-40"
          style={{ background: aiState === "done" ? "#F0FDF4" : "#1C1917", color: aiState === "done" ? "#15803D" : "#fff" }}>
          {aiState === "running" ? L("读取中…", "Reading…") : aiState === "done" ? "✓ " + L("已填入", "Filled")
            : <span className="flex items-center justify-center gap-1.5"><FB.UI.Icon name="spark" size={15} />{L("自动读发票", "Auto-read")}</span>}
        </button>
        {aiState === "done" && (
          <button onClick={() => runExtract(true)} className="px-4 h-11 rounded-xl border border-stone-300 text-stone-500 text-[12px]">
            ↻ {L("重读", "Redo")}
          </button>
        )}
      </div>
      {ai && ai.cached && <p className="text-[11px] text-stone-400 px-1 -mt-2 mb-2">{L("用的是上次读的结果，没再花额度", "cached — no new API call")}</p>}
      {ai && ai.error && (
        <div className="rounded-xl p-3 mb-3 text-[12px]" style={{ background: "#FEF2F2", color: "#991B1B" }}>{String(ai.error).slice(0, 160)}</div>
      )}

      {countedAfter && countedAfter.size > 0 && (
        <div className="rounded-xl p-3 mb-3 text-[12px] leading-snug" style={{ background: "#FDF2E8", color: "#633806", borderLeft: "3px solid #C2540A" }}>
          <b>{L("到货之后盘过点。", "Counted after arrival.")}</b>
          {L("下面标红的行可能已经被盘进库存 — 直接入库会算两次。建议那几行点「不入库」,价格照记。",
             " Marked lines may already be in the count — approving adds them twice. Tap 'no stock' on those lines; price still records.")}
        </div>
      )}

      <div className="rounded-xl border border-stone-200 bg-white p-3 mb-3">
        <input value={inv.supplier} onChange={(e) => setInv({ ...inv, supplier: e.target.value })}
          placeholder={L("供应商", "Supplier")} className="w-full h-10 px-3 rounded-xl border border-stone-300 text-sm mb-1" />
        {inv.raw && FB.sameSupplier(inv.raw, inv.supplier) === false && (
          <p className="text-[10px] text-[#C2540A] mb-1">{L("单上写", "invoice says")}「{inv.raw}」</p>
        )}
        {inv.raw && !inv.alias_known && String(inv.raw).trim() && FB.sameSupplier(inv.raw, inv.supplier) && (
          <label className="flex items-center gap-1.5 mb-2 text-[11px] text-stone-500">
            <input type="checkbox" checked={learnSupp} onChange={(e) => setLearnSupp(e.target.checked)} className="w-3.5 h-3.5 accent-red-700" />
            {L("以后自动认「" + inv.raw + "」= " + inv.supplier, "remember this supplier name")}
          </label>
        )}
        {inv.alias_known && <p className="text-[10px] text-[#4A7A1C] mb-2">✓ {L("认得这个供应商名", "known supplier")}</p>}
        <div className="flex gap-2 mb-3">
          <input value={inv.no} onChange={(e) => setInv({ ...inv, no: e.target.value })}
            placeholder={L("发票号", "Invoice #")} className="flex-1 h-10 px-3 rounded-xl border border-stone-300 text-sm" />
          <input value={inv.total} onChange={(e) => setInv({ ...inv, total: e.target.value })}
            type="number" inputMode="decimal" placeholder={L("总额", "Total")}
            className="w-28 h-10 px-3 rounded-xl border border-stone-300 text-sm text-right" />
        </div>

        {rows.map((r, i) => {
          const amt = Number(r.amount) || (Number(r.qty) || 0) * (Number(r.unit_price) || 0);
          const pk = Number(r.pack) > 0 ? Number(r.pack) : 1;
          const baseQty = Math.round((Number(r.qty) || 0) * pk * 1000) / 1000;
          const basePrice = Number(r.unit_price) > 0 ? Number(r.unit_price) / pk : 0;
          const short = r.qty_ordered != null ? r.qty_ordered - baseQty : null;
          const rise = r.old_price && basePrice ? ((basePrice - r.old_price) / r.old_price) * 100 : null;
          const itemSupp = r.item_code && itemMap[r.item_code] ? itemMap[r.item_code].supplier_name : null;
          const notPrimary = r.is_primary != null
            ? (r.item_code ? !r.is_primary : false)
            : !!(r.item_code && itemSupp && inv.supplier && !FB.sameSupplier(itemSupp, inv.supplier));
          return (
            <div key={i} className="py-2.5 border-t border-stone-100"
              style={!r.item_code && !r.skip_stock ? { background: "#FDF2E8", marginLeft: -12, marginRight: -12, paddingLeft: 12, paddingRight: 12 } : {}}>
              <p className="text-[13px] text-stone-800 leading-snug">{r.raw_name}</p>

              <div className="flex items-center gap-1.5 mt-1.5">
                <select value={r.item_code} onChange={(e) => setR(i, "item_code", e.target.value)}
                  className="flex-1 min-w-0 h-9 px-2 rounded-lg border text-[12px] bg-white"
                  style={{ borderColor: r.item_code ? "#E7E5E4" : "#C2540A" }}>
                  <option value="">{r.skip_stock ? L("— 不入库 —", "— no stock —") : "" + L("选品项", "pick item")}</option>
                  {opts.map((o) => <option key={o.code} value={o.code}>{o.code} {lang === "zh" ? o.name_cn : o.name_en}</option>)}
                </select>
                <button onClick={() => setR(i, "skip_stock", !r.skip_stock)}
                  className="px-2 h-9 rounded-lg border text-[11px] shrink-0"
                  style={r.skip_stock ? { background: "#F5F5F4", borderColor: "#D6D3D1", color: "#57534E" } : { borderColor: "#E7E5E4", color: "#A8A29E" }}>
                  {r.skip_stock ? "" + L("不入库", "no stock") : L("不入库", "no stock")}
                </button>
              </div>

              <div className="flex items-center gap-1.5 mt-1.5">
                <input type="number" inputMode="decimal" value={r.qty} onChange={(e) => setR(i, "qty", e.target.value)}
                  placeholder={L("量", "qty")} className="w-14 h-9 px-1 rounded-lg border border-stone-300 text-center text-sm" />
                <span className="text-[11px] text-stone-500 w-11 truncate">{r.unit}</span>
                <span className="text-[10px] text-stone-400">× RM</span>
                <input type="number" inputMode="decimal" value={r.unit_price} onChange={(e) => setR(i, "unit_price", e.target.value)}
                  placeholder="0.00" className="w-16 h-9 px-1 rounded-lg border border-stone-300 text-center text-sm" />
                <span className="ml-auto text-[13px] font-medium text-stone-800 tabular-nums">{amt ? amt.toFixed(2) : ""}</span>
              </div>

              {r.item_code && !r.skip_stock && r.item_unit && (
                <div className="flex items-center gap-1.5 mt-1.5 pl-1" style={{ borderLeft: "2px solid #E7E5E4" }}>
                  <span className="text-[10px] text-stone-400">{L("入库", "stock")}</span>
                  <span className="text-[10px] text-stone-400">1 {r.unit} =</span>
                  <input type="number" inputMode="decimal" value={r.pack}
                    onChange={(e) => setR(i, "pack", e.target.value)}
                    className="w-14 h-8 px-1 rounded-lg border text-center text-[13px]"
                    style={{ borderColor: Number(r.pack) !== 1 ? "#C2540A" : "#E7E5E4" }} />
                  <span className="text-[10px] text-stone-400">{r.item_unit}</span>
                  <span className="ml-auto text-[12px] font-medium tabular-nums" style={{ color: "#B91C1C" }}>
                    {baseQty ? baseQty + " " + r.item_unit : ""}
                    {basePrice ? " @ " + basePrice.toFixed(3) : ""}
                  </span>
                </div>
              )}

              <div className="flex flex-wrap gap-x-3 gap-y-0.5 mt-1">
                {r.pack_text && <span className="text-[10px] text-stone-500">{L("单上规格", "spec")}: {r.pack_text}</span>}
                {r.unit_match === false && Number(r.pack) === 1 && (
                  <span className="text-[10px] text-[#C2540A]">{L("单位不同，请设折算", "set conversion")}</span>
                )}
                {r.matched_by === "alias" && <span className="text-[10px] text-[#4A7A1C]">✓ {L("认得这个叫法", "known alias")}</span>}
                {r.matched_by === "ai" && <span className="text-[10px] text-[#C2540A]">{L("AI 猜的，请确认", "AI guess")}</span>}
                {short != null && Math.abs(short) > 0.001 && (
                  <span className="text-[10px] text-[#C2540A]">{short > 0 ? L("少 ", "short ") + short : L("多 ", "over ") + -short}</span>
                )}
                {rise != null && Math.abs(rise) > 0.5 && (
                  <span className="text-[10px]" style={{ color: Math.abs(rise) > 15 ? "#B91C1C" : "#C2540A" }}>
                    {r.old_price} → {r.unit_price} ({rise > 0 ? "+" : ""}{rise.toFixed(1)}%)
                  </span>
                )}
                {countedAfter && countedAfter.has(r.item_code) && !r.skip_stock && (
                  <span className="text-[10px] font-semibold" style={{ color: "#A81E12" }}>
                    {L("到货后盘过点 → 建议不入库", "counted after arrival → skip stock")}
                  </span>
                )}
                {notPrimary && !r.skip_stock && (
                  <span className="text-[10px] text-stone-500">
                    {L("非主供应商(" + (itemSupp || "?") + ")，只记价不改成本", "alt supplier — price only")}
                  </span>
                )}
                {!notPrimary && r.item_code && !r.skip_stock && r.unit_price && (
                  <span className="text-[10px] text-[#4A7A1C]">{L("主供应商，会更新买价", "primary — updates cost")}</span>
                )}
              </div>

              {r.item_code && r.raw_name && r.matched_by !== "alias" && !r.skip_stock && (
                <label className="flex items-center gap-1.5 mt-1.5 text-[11px] text-stone-500">
                  <input type="checkbox" checked={r.learn} onChange={(e) => setR(i, "learn", e.target.checked)} className="w-3.5 h-3.5 accent-red-700" />
                  {L("以后自动认这个叫法", "remember this name")}
                </label>
              )}
            </div>
          );
        })}

        <div className="flex justify-between items-center pt-2 mt-1 border-t-2 border-stone-800">
          <span className="text-[12px] text-stone-500">{L("行小计", "Sum")}</span>
          <span className="text-[15px] font-semibold tabular-nums">RM {sum.toFixed(2)}</span>
        </div>
        {diff != null && Math.abs(diff) > 0.02 && (
          <p className="text-[11px] mt-1.5" style={{ color: "#C2540A" }}>
            {L("和发票总额差", "differs")} RM {Math.abs(diff).toFixed(2)}
          </p>
        )}
        {diff != null && Math.abs(diff) <= 0.02 && (
          <p className="text-[11px] mt-1.5 text-[#4A7A1C]">✓ {L("算得平 — 数字应该没读错", "balanced — numbers check out")}</p>
        )}
        {unmapped > 0 && (
          <p className="text-[11px] mt-1 text-[#C2540A]">{unmapped} {L("行还没对上码，选品项或标不入库", "unmapped — pick or skip")}</p>
        )}
      </div>

      {msg && (
        <div className="rounded-xl p-3 mb-3 text-[12px]"
          style={msg.ok ? { background: "#F0FDF4", color: "#15803D" } : { background: "#FEF2F2", color: "#991B1B" }}>
          {msg.ok ? (
            <>
              ✓ {L("已入库", "Approved")} · {msg.r.stocked} {L("项", "items")}
              {msg.r.price_updates.length > 0 && <div className="mt-1">{L("更新买价", "price updated")}: {msg.r.price_updates.map((p) => p.item_code).join(", ")}</div>}
              {msg.r.alt_prices.length > 0 && <div className="mt-1">{L("只记比价", "alt price only")}: {msg.r.alt_prices.map((p) => p.item_code).join(", ")}</div>}
              {msg.r.alias_added.length > 0 && <div className="mt-1">{L("学会品名", "learned")}: {msg.r.alias_added.join(", ")}</div>}
              {msg.r.supplier_alias_added && <div className="mt-1">{L("学会供应商名", "supplier alias")}: {msg.r.supplier_alias_added}</div>}
            </>
          ) : String(msg.text).slice(0, 160)}
        </div>
      )}

      {zoom && (
        <div onClick={() => setZoom(null)} className="fixed inset-0 z-50 flex items-center justify-center p-4" style={{ background: "rgba(0,0,0,.85)" }}>
          <img src={zoom} alt="" className="max-w-full max-h-full object-contain rounded-xl" />
        </div>
      )}

      <div className="fixed bottom-14 left-0 right-0 px-4 py-3 pb-safe flex gap-2" style={{ background: "linear-gradient(to top,#FAFAF9 70%,transparent)" }}>
        <button onClick={reject} disabled={busy}
          className="px-4 h-12 rounded-xl border border-stone-300 text-stone-500 text-sm">{L("退回", "Reject")}</button>
        <button onClick={approve} disabled={busy}
          className="flex-1 h-12 rounded-xl bg-red-700 text-white font-medium active:scale-[0.98] disabled:opacity-40">
          {busy ? "…" : L("确认入库", "Approve")}
        </button>
      </div>
    </div>
  );
};
