// หน้าสต็อกอะไหล่ — ฟีเจอร์เต็มเหมือนสต็อกสินค้า แต่ล็อกหมวด "อะไหล่" (มีแต่หมวดย่อย ไม่มีหมวดหลักอื่น)
function PartsPage({ ui, user }) {
  const { st, dispatch } = useStore();
  const toast = useToast();
  const [q, setQ] = React.useState("");
  const [cat, setCat] = React.useState("ทั้งหมด");
  const [sub, setSub] = React.useState("ทั้งหมด");
  const [openId, setOpenId] = React.useState(null);
  const [showAdd, setShowAdd] = React.useState(false);
  const [showCats, setShowCats] = React.useState(false);
  const [delTarget, setDelTarget] = React.useState(null);
  const [delCat, setDelCat] = React.useState(null);
  const [editCat, setEditCat] = React.useState(null);
  const [bcTarget, setBcTarget] = React.useState(null);
  const [adj, setAdj] = React.useState({ locId: "", qty: "" });
  const [qtySort, setQtySort] = React.useState(null); // null=ปกติ, "desc"=มาก→น้อย, "asc"=น้อย→มาก
  const [nf, setNf] = React.useState({ name: "", cat: "อะไหล่", sub: "", brand: "OEM", brandOther: "", barcode: "", price: "", wprice: "", cost: "", reorder: 5, img: null, initQty: "", initLoc: "" });
  const [nsub, setNsub] = React.useState({});
  const [ncat, setNcat] = React.useState({ name: "", prefix: "" });

  const isOwner = user.role === "owner";
  const role = st.roles[user.role] || {};
  const canManage = isOwner || role.partsAccess === "all";
  const partsAllBranch = role.allBranch || role.partsAccess === "all";
  const [stockView, setStockView] = React.useState(partsAllBranch ? "ALL" : user.branch);

  const partCats = st.cats.filter((c) => c.parts);
  const partCatNames = partCats.map((c) => c.name);
  // หมวดย่อยที่แสดงในแถบกรอง (รวมทุกหมวดอะไหล่เมื่อเลือก "ทั้งหมด")
  const subOpts = cat === "ทั้งหมด"
    ? [...new Set(partCats.flatMap((c) => c.subs))]
    : (partCats.find((c) => c.name === cat) || { subs: [] }).subs;

  const qOf = (pp) => stockView === "ALL" ? stockTotal(pp) : stockInBranch(st, pp, stockView);
  const products = st.products.filter((p) =>
    partCatNames.includes(p.cat) &&
    (cat === "ทั้งหมด" || p.cat === cat) &&
    (sub === "ทั้งหมด" || p.sub === sub) &&
    (q === "" || (p.name + p.sku + p.barcode + (p.sub || "") + (p.brand || "")).toLowerCase().includes(q.toLowerCase()))
  );
  if (qtySort === "desc") products.sort((a, b) => qOf(b) - qOf(a));
  else if (qtySort === "asc") products.sort((a, b) => qOf(a) - qOf(b));
  const p = st.products.find((x) => x.id === openId);

  const nfBrand = nf.brand === "อื่นๆ" ? (nf.brandOther || "อื่นๆ") : nf.brand;
  const skuPreview = peekSku(st, nf.cat, nfBrand);
  const addCat = () => {
    if (!ncat.name || !ncat.prefix) { toast("กรอกชื่อหมวดและตัวย่อ (เช่น SP)", "danger"); return; }
    dispatch({ type: "CAT_ADD", name: ncat.name, prefix: ncat.prefix.toUpperCase().slice(0, 4), parts: true });
    toast(`เพิ่มหมวดอะไหล่ ${ncat.name} แล้ว`);
    setNcat({ name: "", prefix: "" });
  };

  const doAdjust = (sign) => {
    if (!adj.locId || !adj.qty) { toast("เลือก Location และจำนวนก่อน", "danger"); return; }
    dispatch({ type: "ADJUST", productId: p.id, locId: adj.locId, delta: sign * Number(adj.qty), by: user.id, reason: sign > 0 ? "รับอะไหล่เข้า" : "ปรับยอด/ตัดของเสีย" });
    toast("บันทึกความเคลื่อนไหวแล้ว");
    setAdj({ locId: "", qty: "" });
  };

  const addProduct = () => {
    if (!nf.name || !nf.price) { toast("กรอกชื่ออะไหล่และราคา", "danger"); return; }
    dispatch({
      type: "PRODUCT_ADD", by: user.id, product: {
        name: nf.name, cat: nf.cat, sub: nf.sub || "อื่นๆ", brand: nfBrand,
        price: Number(nf.price), wprice: nf.wprice === "" ? null : Number(nf.wprice), cost: Number(nf.cost) || 0, reorder: Number(nf.reorder) || 0,
        barcode: nf.barcode || `885000${Date.now() % 10000000}`, img: nf.img,
        initQty: Number(nf.initQty) || 0, initLoc: nf.initLoc,
      },
    });
    toast(`เพิ่มอะไหล่แล้ว · ${skuPreview}`);
    setShowAdd(false);
    setNf({ name: "", cat: partCatNames[0] || "อะไหล่", sub: "", brand: "OEM", brandOther: "", barcode: "", price: "", wprice: "", cost: "", reorder: 5, img: null, initQty: "", initLoc: "" });
  };

  const doDelete = () => {
    const m = (delTarget.sku || "").match(/(\d+)$/);
    dispatch({ type: "PRODUCT_DEL", id: delTarget.id });
    toast(`ลบ ${delTarget.name} แล้ว · เลขรัน ${m ? Number(m[1]) : "—"} จะถูกนำกลับมาใช้ใหม่`, "info");
    setDelTarget(null); setOpenId(null);
  };

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 13 }}>
      <Card style={{ padding: 14, display: "flex", gap: 10, alignItems: "center", flexWrap: "wrap" }}>
        <div style={{ flex: 1, minWidth: 220 }}><SearchBox value={q} onChange={setQ} placeholder="ค้นหาชื่อ / SKU / บาร์โค้ด / ยี่ห้อ…" /></div>
        {partsAllBranch && (
          <Select value={stockView} onChange={setStockView} style={{ width: 170, fontWeight: 700, color: T.primary }}
            options={[{ value: "ALL", label: "ทุกสาขา (รวม)" }, ...st.branches.map((b) => ({ value: b.id, label: b.name }))]} />
        )}
        {isOwner && <Btn kind="ghost" onClick={() => setShowCats(true)}>☰ จัดการหมวดหมู่</Btn>}
        {canManage && <Btn onClick={() => { setNf((x) => ({ ...x, cat: cat === "ทั้งหมด" ? (partCatNames[0] || "อะไหล่") : cat, sub: "" })); setShowAdd(true); }}>⊕ เพิ่มอะไหล่</Btn>}
      </Card>

      {partCats.length > 1 && (
        <div style={{ display: "flex", gap: 6, flexWrap: "wrap", alignItems: "center" }}>
          {["ทั้งหมด", ...partCatNames].map((c) => (
            <Btn key={c} sm kind={cat === c ? "primary" : "ghost"} onClick={() => { setCat(c); setSub("ทั้งหมด"); }}>{c}</Btn>
          ))}
        </div>
      )}

      <div style={{ display: "flex", gap: 6, flexWrap: "wrap", alignItems: "center" }}>
        {["ทั้งหมด", ...subOpts].map((s) => (
          <Btn key={s} sm kind={sub === s ? "info" : "ghost"} onClick={() => setSub(s)}>{s}</Btn>
        ))}
      </div>

      <Card style={{ padding: "4px 18px 8px" }}>
        <div style={{ display: "grid", gridTemplateColumns: "42px 1.5fr 0.85fr 0.62fr 0.62fr 0.62fr 0.55fr 40px", gap: 9, fontSize: 11.5, color: T.sub, fontWeight: 700, padding: "10px 4px 8px", borderBottom: `1px solid ${T.border}` }}>
          <div></div><div>อะไหล่</div><div>หมวดย่อย / SKU</div><div>ราคาขาย</div><div>ราคาส่ง</div><div>ต้นทุน</div>
          <div onClick={() => setQtySort(qtySort === null ? "desc" : qtySort === "desc" ? "asc" : null)}
            title="กดเพื่อเรียงตามจำนวนคงเหลือ"
            style={{ display: "flex", alignItems: "center", gap: 3, cursor: "pointer", userSelect: "none", color: qtySort ? T.primary : T.sub }}>
            คงเหลือ<span style={{ fontSize: 11, opacity: qtySort ? 1 : 0.5 }}>{qtySort === "desc" ? "▼" : qtySort === "asc" ? "▲" : "⇅"}</span>
          </div>
          <div style={{ textAlign: "center" }}>พิมพ์</div>
        </div>
        {products.map((pp, i) => {
          const qty = qOf(pp);
          const tone = qty === 0 ? "danger" : pp.reorder > 0 && qty <= pp.reorder ? "warn" : "ok";
          return (
            <div key={pp.id} className="ss-row" onClick={() => setOpenId(pp.id)} style={{ display: "grid", gridTemplateColumns: "42px 1.5fr 0.85fr 0.62fr 0.62fr 0.62fr 0.55fr 40px", gap: 9, alignItems: "center", fontSize: 13, padding: "8px 4px", borderBottom: i < products.length - 1 ? `1px solid ${T.rowBorder}` : "none", cursor: "pointer", animation: `ss-rise .3s ${Math.min(i * 25, 250)}ms ease backwards` }}>
              <ProductImg p={pp} size={38} />
              <div style={{ minWidth: 0 }}>
                <div style={{ fontWeight: 600, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{pp.name}</div>
                <div style={{ fontSize: 10.5, color: T.sub }}>{pp.brand || "—"}</div>
              </div>
              <div style={{ fontSize: 11.5, color: T.sub }}>{pp.sub || "—"}<br /><span style={{ fontFamily: "monospace", fontSize: 10 }}>{pp.sku}</span></div>
              <div style={{ fontWeight: 700 }}>{fmtMoney(pp.price)}</div>
              <div style={{ color: T.primary, fontWeight: 600 }}>{pp.wprice != null && pp.wprice !== "" ? fmtMoney(pp.wprice) : "—"}</div>
              <div style={{ color: T.sub }}>{fmtMoney(pp.cost)}</div>
              <div style={{ fontFamily: T.headFont, fontWeight: 800, fontSize: 15, color: tone === "danger" ? T.accent : tone === "warn" ? "#C77700" : T.text }}>{qty}</div>
              <button className="ss-btn" title="พิมพ์บาร์โค้ด" onClick={(e) => { e.stopPropagation(); setBcTarget(pp); }} style={{ justifySelf: "center", width: 30, height: 30, borderRadius: 8, border: `1.5px solid #E8943A`, background: "#FFF3E6", color: "#C77700", cursor: "pointer", fontSize: 14, display: "flex", alignItems: "center", justifyContent: "center" }}>🖨</button>
            </div>
          );
        })}
        {products.length === 0 && <EmptyState text="ไม่พบอะไหล่" />}
      </Card>

      {/* ── รายละเอียดอะไหล่ ── */}
      <Modal open={!!p} onClose={() => { setOpenId(null); setAdj({ locId: "", qty: "" }); }} title={p ? p.name : ""} width={620}
        footer={p && <React.Fragment>
          {canManage && <Btn kind="dangerSoft" sm onClick={() => setDelTarget(p)} style={{ marginRight: "auto" }}>🗑 ลบอะไหล่</Btn>}
          <Btn kind="warn" onClick={() => setBcTarget(p)}>🖨 พิมพ์บาร์โค้ด</Btn>
          <Btn kind="ghost" onClick={() => setOpenId(null)}>ปิด</Btn>
        </React.Fragment>}>
        {p && (
          <div style={{ display: "flex", flexDirection: "column", gap: 15 }}>
            <div style={{ display: "flex", gap: 16 }}>
              <ImgUpload value={p.img} onChange={(v) => dispatch({ type: "PRODUCT_SET", id: p.id, patch: { img: v } })} size={84} hint="รูปอะไหล่" />
              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr 1fr", gap: 10, flex: 1 }}>
                <Field label="ราคาขาย"><NumInput value={p.price} onChange={(e) => dispatch({ type: "PRODUCT_SET", id: p.id, patch: { price: Number(e.target.value) || 0 } })} /></Field>
                <Field label="ราคาส่ง"><NumInput value={p.wprice != null ? p.wprice : ""} onChange={(e) => dispatch({ type: "PRODUCT_SET", id: p.id, patch: { wprice: e.target.value === "" ? null : Number(e.target.value) } })} /></Field>
                <Field label="ต้นทุน"><NumInput value={p.cost} onChange={(e) => dispatch({ type: "PRODUCT_SET", id: p.id, patch: { cost: Number(e.target.value) || 0 } })} /></Field>
                <Field label="จุดสั่งซื้อ"><NumInput value={p.reorder} onChange={(e) => dispatch({ type: "PRODUCT_SET", id: p.id, patch: { reorder: Number(e.target.value) || 0 } })} /></Field>
              </div>
            </div>
            <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10 }}>
              <Field label="หมวดหลัก">
                <Select value={p.cat} onChange={(v) => dispatch({ type: "PRODUCT_SET", id: p.id, patch: { cat: v, sub: "" } })} options={partCatNames} />
              </Field>
              <Field label="หมวดย่อย">
                <Select value={p.sub || ""} onChange={(v) => dispatch({ type: "PRODUCT_SET", id: p.id, patch: { sub: v } })} placeholder="— เลือก —" options={(partCats.find((c) => c.name === p.cat) || { subs: [] }).subs} />
              </Field>
            </div>
            <div style={{ display: "flex", gap: 18, alignItems: "center", background: T.chipBg, borderRadius: 12, padding: "10px 16px" }}>
              <BarcodeArt value={p.barcode} height={30} />
              <div style={{ fontSize: 12, color: T.sub }}>SKU: <b style={{ fontFamily: "monospace" }}>{p.sku}</b> · ยี่ห้อ: {p.brand || "—"}<br />คงเหลือรวมทุกสาขา: <b style={{ color: T.text }}>{stockTotal(p)} ชิ้น</b></div>
            </div>
            <div>
              <SectionTitle>คงเหลือรายตำแหน่ง (Location)</SectionTitle>
              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8 }}>
                {Object.entries(p.stock).length === 0 && <div style={{ fontSize: 12.5, color: T.sub }}>ไม่มีสต็อกคงเหลือ</div>}
                {Object.entries(p.stock).map(([locId, qq]) => (
                  <div key={locId} style={{ display: "flex", alignItems: "center", gap: 9, border: `1px solid ${T.border}`, borderRadius: 10, padding: "8px 12px", fontSize: 12.5 }}>
                    <span style={{ width: 26, height: 26, borderRadius: 7, background: T.infoBg, color: T.primary, fontWeight: 800, fontSize: 11, display: "flex", alignItems: "center", justifyContent: "center" }}>
                      {(st.locations.find((l) => l.id === locId) || {}).code || "?"}
                    </span>
                    {locName(st, locId)}
                    <b style={{ marginLeft: "auto", fontFamily: T.headFont, fontSize: 15 }}>{qq}</b>
                  </div>
                ))}
              </div>
            </div>
            {canManage && (
              <div>
                <SectionTitle>รับเข้า / ปรับยอด</SectionTitle>
                <div style={{ display: "flex", gap: 8 }}>
                  <Select value={adj.locId} onChange={(v) => setAdj((x) => ({ ...x, locId: v }))} placeholder="— Location —" style={{ flex: 1.4 }}
                    options={st.locations.map((l) => ({ value: l.id, label: locName(st, l.id) }))} />
                  <NumInput value={adj.qty} min="1" placeholder="จำนวน" onChange={(e) => setAdj((x) => ({ ...x, qty: e.target.value }))} style={{ width: 90 }} />
                  <Btn sm kind="ok" onClick={() => doAdjust(1)}>+ รับเข้า</Btn>
                  <Btn sm kind="dangerSoft" onClick={() => doAdjust(-1)}>− ตัดออก</Btn>
                </div>
                <div style={{ fontSize: 11.5, color: T.sub, marginTop: 7 }}>ทุกการปรับยอดถูกบันทึกในรายการเคลื่อนไหวอัตโนมัติ</div>
              </div>
            )}
          </div>
        )}
      </Modal>

      {/* ── ยืนยันลบอะไหล่ ── */}
      <Modal open={!!delTarget} onClose={() => setDelTarget(null)} title="ยืนยันการลบอะไหล่" width={430}
        footer={<React.Fragment>
          <Btn kind="ghost" onClick={() => setDelTarget(null)}>ยกเลิก</Btn>
          <Btn kind="danger" onClick={doDelete}>🗑 ลบอะไหล่</Btn>
        </React.Fragment>}>
        {delTarget && (
          <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
            <div style={{ display: "flex", alignItems: "center", gap: 10, background: T.dangerBg, borderRadius: 12, padding: "10px 14px" }}>
              <ProductImg p={delTarget} size={42} />
              <div>
                <div style={{ fontWeight: 700, fontSize: 13.5 }}>{delTarget.name}</div>
                <div style={{ fontSize: 11.5, color: T.dangerFg, fontFamily: "monospace" }}>{delTarget.sku}</div>
              </div>
            </div>
            <div style={{ fontSize: 12.5, color: T.sub, lineHeight: 1.6 }}>
              สต็อกคงเหลือ {stockTotal(delTarget)} ชิ้นจะถูกลบไปด้วย ·
              เลขรันท้าย SKU จะถูก<b>นำกลับมาใช้กับอะไหล่ใหม่ชิ้นถัดไป</b>โดยอัตโนมัติ
            </div>
          </div>
        )}
      </Modal>

      {/* ── เพิ่มอะไหล่ ── */}
      <Modal open={showAdd} onClose={() => setShowAdd(false)} title="เพิ่มอะไหล่ใหม่" width={640}
        footer={<React.Fragment>
          <div style={{ marginRight: "auto", fontSize: 12, color: T.sub }}>SKU อัตโนมัติ: <b style={{ fontFamily: "monospace", color: T.primary }}>{skuPreview}</b></div>
          <Btn kind="ghost" onClick={() => setShowAdd(false)}>ยกเลิก</Btn>
          <Btn onClick={addProduct}>บันทึกอะไหล่</Btn>
        </React.Fragment>}>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
          <Field label="ชื่ออะไหล่" req style={{ gridColumn: "1/-1" }}><TextInput value={nf.name} onChange={(e) => setNf((x) => ({ ...x, name: e.target.value }))} /></Field>
          <Field label="หมวดหลัก">
            <Select value={nf.cat} onChange={(v) => setNf((x) => ({ ...x, cat: v, sub: "" }))} options={partCatNames} />
          </Field>
          <Field label="หมวดย่อย">
            <Select value={nf.sub} onChange={(v) => setNf((x) => ({ ...x, sub: v }))} placeholder="— เลือก / เพิ่มในจัดการหมวด —" options={(partCats.find((c) => c.name === nf.cat) || { subs: [] }).subs} />
          </Field>
          <Field label="ยี่ห้อ (ใช้รัน SKU)">
            <Select value={nf.brand} onChange={(v) => setNf((x) => ({ ...x, brand: v }))} options={BRANDS} />
          </Field>
          {nf.brand === "อื่นๆ"
            ? <Field label="ระบุยี่ห้อ"><TextInput value={nf.brandOther} onChange={(e) => setNf((x) => ({ ...x, brandOther: e.target.value }))} /></Field>
            : <Field label="รูปอะไหล่"><ImgUpload value={nf.img} onChange={(v) => setNf((x) => ({ ...x, img: v }))} size={52} /></Field>}
          {nf.brand === "อื่นๆ" && <Field label="รูปอะไหล่"><ImgUpload value={nf.img} onChange={(v) => setNf((x) => ({ ...x, img: v }))} size={52} /></Field>}
          <Field label="ราคาขาย (บาท)" req><NumInput value={nf.price} onChange={(e) => setNf((x) => ({ ...x, price: e.target.value }))} /></Field>
          <Field label="ราคาส่ง (บาท)"><NumInput value={nf.wprice} onChange={(e) => setNf((x) => ({ ...x, wprice: e.target.value }))} /></Field>
          <Field label="ต้นทุน (บาท)"><NumInput value={nf.cost} onChange={(e) => setNf((x) => ({ ...x, cost: e.target.value }))} /></Field>
          <Field label="บาร์โค้ด (เว้นว่าง = สร้างอัตโนมัติ)"><TextInput value={nf.barcode} onChange={(e) => setNf((x) => ({ ...x, barcode: e.target.value }))} /></Field>
          <Field label="จุดสั่งซื้อ (แจ้งเตือนใกล้หมด)"><NumInput value={nf.reorder} onChange={(e) => setNf((x) => ({ ...x, reorder: e.target.value }))} /></Field>
          <Field label="จำนวนเริ่มต้น"><NumInput value={nf.initQty} onChange={(e) => setNf((x) => ({ ...x, initQty: e.target.value }))} /></Field>
          <Field label="เก็บที่ Location">
            <Select value={nf.initLoc} onChange={(v) => setNf((x) => ({ ...x, initLoc: v }))} placeholder="— เลือก —"
              options={st.locations.map((l) => ({ value: l.id, label: locName(st, l.id) }))} />
          </Field>
        </div>
      </Modal>

      {/* ── จัดการหมวดหมู่ & หมวดย่อยอะไหล่ ── */}
      <Modal open={showCats} onClose={() => setShowCats(false)} title="จัดการหมวดหมู่ & หมวดย่อย (อะไหล่)" width={560}>
        <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
          {partCats.map((c) => (
            <div key={c.name} style={{ border: `1px solid ${T.border}`, borderRadius: 12, padding: "12px 15px" }}>
              <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 8 }}>
                {editCat && editCat.orig === c.name ? (
                  <React.Fragment>
                    <TextInput value={editCat.name} onChange={(e) => setEditCat((x) => ({ ...x, name: e.target.value }))} style={{ padding: "5px 10px", fontSize: 13, width: 150 }} />
                    <TextInput value={editCat.prefix} onChange={(e) => setEditCat((x) => ({ ...x, prefix: e.target.value.toUpperCase() }))} style={{ padding: "5px 10px", fontSize: 13, width: 70 }} />
                    <Btn sm kind="ok" onClick={() => { dispatch({ type: "CAT_SET", name: c.name, patch: { name: editCat.name.trim() || c.name, prefix: (editCat.prefix || c.prefix).slice(0, 4) } }); toast("แก้ไขหมวดแล้ว"); setEditCat(null); }}>บันทึก</Btn>
                    <Btn sm kind="ghost" onClick={() => setEditCat(null)}>ยกเลิก</Btn>
                  </React.Fragment>
                ) : (
                  <React.Fragment>
                    <span style={{ fontFamily: T.headFont, fontWeight: 700, fontSize: 14 }}>{c.name}</span>
                    <Badge sm tone="info">SKU: {c.prefix}-ยี่ห้อ-XXXXXX</Badge>
                    <span style={{ fontSize: 11, color: T.sub }}>{st.products.filter((x) => x.cat === c.name).length} รายการ</span>
                    {isOwner && (
                      <div style={{ marginLeft: "auto", display: "flex", gap: 6 }}>
                        <button className="ss-btn" onClick={() => setEditCat({ orig: c.name, name: c.name, prefix: c.prefix })} style={{ border: `1px solid ${T.border}`, background: "#fff", borderRadius: 7, padding: "4px 10px", fontSize: 11.5, fontWeight: 700, cursor: "pointer", color: T.sub, fontFamily: T.bodyFont }}>✎ แก้ไข</button>
                        <button className="ss-btn" onClick={() => setDelCat(c)} style={{ border: "none", background: T.dangerBg, color: T.dangerFg, borderRadius: 7, padding: "4px 9px", fontSize: 11.5, fontWeight: 700, cursor: "pointer", fontFamily: T.bodyFont }}>✕</button>
                      </div>
                    )}
                  </React.Fragment>
                )}
              </div>
              <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>
                {c.subs.map((s) => (
                  <span key={s} style={{ display: "inline-flex", alignItems: "center", gap: 5, background: T.chipBg, border: `1px solid ${T.border}`, borderRadius: 999, padding: "4px 6px 4px 12px", fontSize: 12, fontWeight: 600 }}>
                    {s}
                    <a onClick={() => dispatch({ type: "SUB_DEL", cat: c.name, sub: s })}
                      style={{ cursor: "pointer", color: T.sub, width: 17, height: 17, borderRadius: "50%", display: "inline-flex", alignItems: "center", justifyContent: "center", fontSize: 10, background: "#fff" }}>✕</a>
                  </span>
                ))}
                <div style={{ display: "flex", gap: 5 }}>
                  <TextInput value={nsub[c.name] || ""} placeholder="+ หมวดย่อยใหม่"
                    onChange={(e) => setNsub((x) => ({ ...x, [c.name]: e.target.value }))}
                    onKeyDown={(e) => { if (e.key === "Enter" && nsub[c.name]) { dispatch({ type: "SUB_ADD", cat: c.name, sub: nsub[c.name].trim() }); setNsub((x) => ({ ...x, [c.name]: "" })); } }}
                    style={{ padding: "4px 10px", fontSize: 12, width: 130, borderRadius: 999 }} />
                  <Btn sm kind="soft" disabled={!nsub[c.name]} onClick={() => { dispatch({ type: "SUB_ADD", cat: c.name, sub: nsub[c.name].trim() }); setNsub((x) => ({ ...x, [c.name]: "" })); }}>เพิ่ม</Btn>
                </div>
              </div>
            </div>
          ))}
          <div style={{ background: T.chipBg, borderRadius: 12, padding: "12px 15px" }}>
            <div style={{ fontSize: 12.5, fontWeight: 700, marginBottom: 8 }}>⊕ เพิ่มหมวดหมู่อะไหล่ใหม่</div>
            <div style={{ display: "flex", gap: 8 }}>
              <TextInput value={ncat.name} onChange={(e) => setNcat((x) => ({ ...x, name: e.target.value }))} placeholder="ชื่อหมวด เช่น อะไหล่ Notebook" style={{ flex: 1 }} />
              <TextInput value={ncat.prefix} onChange={(e) => setNcat((x) => ({ ...x, prefix: e.target.value.toUpperCase() }))} placeholder="ตัวย่อ เช่น SN" style={{ width: 110 }} />
              <Btn sm onClick={addCat}>เพิ่ม</Btn>
            </div>
            <div style={{ fontSize: 11, color: T.sub, marginTop: 6 }}>ตัวย่อใช้รันเลขอะไหล่อัตโนมัติ เช่น SN-APPLE-000001</div>
          </div>
        </div>
      </Modal>

      {/* ── ลบหมวดอะไหล่ ── */}
      <Modal open={!!delCat} onClose={() => setDelCat(null)} title="ยืนยันการลบหมวดหมู่" width={420}
        footer={<React.Fragment>
          <Btn kind="ghost" onClick={() => setDelCat(null)}>ยกเลิก</Btn>
          <Btn kind="danger" onClick={() => {
            const cnt = st.products.filter((x) => x.cat === delCat.name).length;
            if (cnt > 0) { toast(`ยังมีอะไหล่ ${cnt} รายการในหมวดนี้ — ย้าย/ลบก่อน`, "danger"); return; }
            if (partCats.length <= 1) { toast("ต้องมีหมวดอะไหล่อย่างน้อย 1 หมวด", "danger"); return; }
            dispatch({ type: "CAT_DEL", name: delCat.name }); toast(`ลบหมวด ${delCat.name} แล้ว`, "info");
            if (cat === delCat.name) setCat("ทั้งหมด"); setDelCat(null);
          }}>✕ ลบหมวด</Btn>
        </React.Fragment>}>
        {delCat && <div style={{ fontSize: 13, lineHeight: 1.7 }}>ลบหมวด <b>{delCat.name}</b>?<br /><span style={{ color: T.sub, fontSize: 12 }}>ลบได้เฉพาะหมวดที่ไม่มีอะไหล่อยู่</span></div>}
      </Modal>

      {/* ── พิมพ์บาร์โค้ด ── */}
      <BarcodePrintModal open={!!bcTarget} onClose={() => setBcTarget(null)} product={bcTarget} />
    </div>
  );
}

window.PartsPage = PartsPage;