/* ============================================================
   Quản trị → Thuộc tính tài liệu — manage the property pool + template sets
   ============================================================ */
// modal shell shared by create/edit property dialogs
function PropModal({ title, sub, onClose, children }) {
  return (
    <div onClick={onClose} style={{ position: "fixed", inset: 0, zIndex: 56, background: "rgba(8,19,23,.5)", backdropFilter: "blur(3px)", display: "grid", placeItems: "center" }}>
      <div onClick={e => e.stopPropagation()} className="card" style={{ width: "min(520px, 94vw)", maxHeight: "90vh", overflowY: "auto", padding: 24, boxShadow: "var(--shadow-lg)" }}>
        <div style={{ display: "flex", alignItems: "flex-start", justifyContent: "space-between", gap: 10 }}>
          <div>
            <div style={{ fontWeight: 800, fontSize: 16 }}>{title}</div>
            {sub && <div style={{ fontSize: 12, color: "var(--ink-3)", fontWeight: 500, marginTop: 2 }}>{sub}</div>}
          </div>
          <button className="icon-btn" onClick={onClose} style={{ width: 28, height: 28, flex: "none" }}>✕</button>
        </div>
        {children}
      </div>
    </div>
  );
}

function PropsAdmin() {
  const auth = (typeof useAuthCtx === "function") ? useAuthCtx() : null;
  const live = !!(auth && auth.user && window.CDE_READY);
  const isAdmin = !!(auth && auth.profile && auth.profile.role === "admin");
  const [props, setProps] = React.useState([]);
  const [myProps, setMyProps] = React.useState([]);        // personal (owner-only) properties
  const [templates, setTemplates] = React.useState([]);
  const [editing, setEditing] = React.useState(null);      // template being edited
  const [creating, setCreating] = React.useState(false);   // new project-property modal
  const [editProp, setEditProp] = React.useState(null);    // project property being edited
  const [creatingMine, setCreatingMine] = React.useState(false);
  const [editMine, setEditMine] = React.useState(null);
  const [editSys, setEditSys] = React.useState(null);      // system field being edited (icon/name)
  window.useSysCfg && window.useSysCfg();                   // re-render when system-field config changes

  const reload = React.useCallback(() => {
    if (!live) { setProps([]); setMyProps([]); setTemplates([]); return; }
    cdeData.docProperties().then(setProps).catch(() => setProps([]));
    cdeData.templates().then(setTemplates).catch(() => setTemplates([]));
    cdeData.userProperties().then(setMyProps).catch(() => setMyProps([]));
  }, [live]);
  React.useEffect(() => { reload(); }, [reload]);

  if (!live) return <div className="content"><div style={{ padding: 40, color: "var(--ink-3)" }}>Đăng nhập để quản lý thuộc tính.</div></div>;

  const delProp = async (p) => { if (!window.confirm(`Xoá thuộc tính "${p.name}"?`)) return; try { await cdeData.deleteProperty(p.id); reload(); } catch (e) { window.alert(e.message); } };
  const delMine = async (p) => { if (!window.confirm(`Xoá thuộc tính cá nhân "${p.name}"?`)) return; try { await cdeData.deleteUserProperty(p.id); reload(); } catch (e) { window.alert(e.message); } };
  const delSys = async (f) => { if (!window.confirm(`Xóa "${f.name}" khỏi dự án?\n\nTrường sẽ biến mất khỏi kho, bảng Tài liệu và panel Tổ chức. (Là trường mặc định nên có thể thêm lại sau.)`)) return; try { await window.saveSysField(f.id, { hidden: true }); } catch (e) { window.alert(e.message); } };
  const restoreSys = async (f) => { try { await window.saveSysField(f.id, { hidden: false }); } catch (e) { window.alert(e.message); } };
  const applyT = async (t) => { try { await cdeData.applyTemplate(t.id); reload(); } catch (e) { window.alert(e.message); } };
  const showAll = async () => { try { await cdeData.showAllProperties(); reload(); } catch (e) { window.alert(e.message); } };
  const delT = async (t) => { if (!window.confirm(`Xoá set "${t.name}"?`)) return; try { await cdeData.deleteTemplate(t.id); reload(); } catch (e) { window.alert(e.message); } };
  const saveCurrent = async () => {
    const active = templates.find(t => t.active);
    const ids = active ? active.propertyIds : props.map(p => p.id);
    const name = window.prompt("Tên set mới:", "Set " + (templates.length + 1));
    if (!name) return;
    try { await cdeData.createTemplate({ name: name.trim(), propertyIds: ids }); reload(); } catch (e) { window.alert(e.message); }
  };
  const nameOf = (id) => { const p = props.find(x => x.id === id); return p ? p.name : null; };
  const allActive = templates.every(t => !t.active);
  const tagChip = { height: 22, padding: "0 9px", borderRadius: 99, background: "var(--sunken)", fontSize: 11.5, fontWeight: 700, color: "var(--ink-2)", display: "inline-flex", alignItems: "center" };
  // built-in fields every document carries, expressed as ordinary select/status
  // properties (same options the organize-by panel and Documents table use);
  // they live in containers columns, so they are not editable/deletable here
  const CLS_COLOR = { idle: "#6b7280", warn: "#f59e0b", str: "#14b8a6", ok: "#10b981", danger: "#ef4444", inf: "#60a5fa" };
  const sysOptions = {
    disc: (window.discOptions ? window.discOptions() : []).map(o => ({ id: o.id, label: o.label, color: o.color })),
    status: Object.entries(window.STATUS || {}).map(([v, o]) => ({ id: v, label: o.label, color: CLS_COLOR[o.cls] || "#6b7280" })),
    type: Object.keys(window.TYPE_META || {}).map(v => ({ id: v, label: v, color: (window.TYPE_META[v] || {}).color || "#6b7280" })),
  };
  const sysType = { disc: "select", status: "status", type: "select" };
  // built-in fields, with admin overrides (icon/name) applied and hidden ones removed
  const systemProps = (window.visibleSysFields ? window.visibleSysFields() : []).map(f => ({
    id: f.id, name: f.name, icon: f.icon, type: sysType[f.id] || "select", system: true, options: sysOptions[f.id] || [],
  }));
  const hiddenSys = window.hiddenSysFields ? window.hiddenSysFields() : [];
  const allProps = [...systemProps, ...props];

  // shared row renderer for any property (system / project / personal)
  const PropRow = ({ p, onEdit, onDel }) => {
    const meta = (window.PROP_TYPES || []).find(t => t.type === p.type) || {};
    const Ico = Icon[meta.icon] || Icon.doc;
    const c = (window.PROP_TYPE_COLORS || {})[p.type] || "#6b7280";
    const opts = p.options || [];
    return (
      <div onMouseEnter={e => { e.currentTarget.style.background = "var(--sunken)"; }}
        onMouseLeave={e => { e.currentTarget.style.background = "transparent"; }}
        style={{ display: "flex", alignItems: "center", gap: 11, padding: "9px 10px", margin: "0 -10px", borderRadius: 10 }}>
        <span style={{ width: 34, height: 34, borderRadius: 10, display: "grid", placeItems: "center", flex: "none", background: c + "22", color: c }}>{p.icon && window.PropIcon ? React.createElement(window.PropIcon, { name: p.icon, size: 16 }) : <Ico size={16} />}</span>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontWeight: 700, fontSize: 13.5, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{p.name}</div>
          <div style={{ fontSize: 11.5, color: "var(--ink-4)", fontWeight: 600, marginTop: 1 }}>{meta.label || p.type}{opts.length ? ` · ${opts.length} lựa chọn` : ""}</div>
        </div>
        {opts.length > 0 && (
          <span style={{ display: "inline-flex", gap: 4, flex: "none" }}>
            {opts.slice(0, 3).map(o => <PropChip key={o.id} o={o} />)}
            {opts.length > 3 && <span style={{ ...tagChip, height: 20, fontSize: 10.5 }}>+{opts.length - 3}</span>}
          </span>
        )}
        {p.system ? (isAdmin ? (<React.Fragment>
          <span title="Thuộc tính hệ thống — dùng chung toàn dự án" style={{ ...tagChip, height: 22, fontSize: 10.5, color: "var(--ink-4)", flex: "none" }}><Icon.shield size={11} />&nbsp;Hệ thống</span>
          <button className="icon-btn" style={{ width: 28, height: 28, flex: "none" }} title="Sửa icon & tên" onClick={() => setEditSys(p)}><Icon.pen size={13} /></button>
          <button className="icon-btn" style={{ width: 28, height: 28, flex: "none" }} title="Xóa khỏi dự án" onClick={() => delSys(p)}><Icon.trash size={13} /></button>
        </React.Fragment>) : (
          <span title="Thuộc tính hệ thống — có sẵn trên mọi hồ sơ"
            style={{ ...tagChip, height: 22, fontSize: 10.5, color: "var(--ink-4)", flex: "none" }}><Icon.shield size={11} />&nbsp;Hệ thống</span>
        )) : onEdit ? (<React.Fragment>
          <button className="icon-btn" style={{ width: 28, height: 28, flex: "none" }} title="Sửa" onClick={() => onEdit(p)}><Icon.pen size={13} /></button>
          <button className="icon-btn" style={{ width: 28, height: 28, flex: "none" }} title="Xoá" onClick={() => onDel(p)}><Icon.trash size={13} /></button>
        </React.Fragment>) : null}
      </div>
    );
  };

  return (
    <div className="content">
      <div style={{ display: "flex", alignItems: "flex-end", justifyContent: "space-between", marginBottom: 20, gap: 12, flexWrap: "wrap" }}>
        <div><div style={{ fontSize: 16, fontWeight: 800 }}>Thuộc tính tài liệu</div>
          <div style={{ fontSize: 12.5, color: "var(--ink-3)", fontWeight: 500, marginTop: 3 }}>Thuộc tính dự án (admin, mọi người thấy) & thuộc tính cá nhân (chỉ riêng bạn)</div></div>
        {isAdmin && <button className="btn primary" onClick={() => setCreating(true)}><Icon.plus size={14} /> Thuộc tính mới</button>}
      </div>
      <div className="grid g-2u" style={{ alignItems: "start" }}>
        <div style={{ display: "grid", gap: 18 }}>
          {/* ---- project pool (admin-managed, everyone sees) ---- */}
          <div className="card card-pad">
            <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 6 }}>
              <div className="card-title">Thuộc tính dự án</div>
              <span style={{ ...tagChip, height: 20, fontSize: 11 }}>{allProps.length}</span>
            </div>
            <div className="card-sub" style={{ marginBottom: 10 }}>Admin quản lý — mọi thành viên thấy, giá trị ghi vào hồ sơ chung</div>
            {allProps.map(p => <PropRow key={p.id} p={p} onEdit={isAdmin ? setEditProp : null} onDel={isAdmin ? delProp : null} />)}
            {isAdmin && (
              <button onClick={() => setCreating(true)}
                style={{ width: "100%", height: 42, borderRadius: 12, border: "1.5px dashed var(--line)", background: "transparent", color: "var(--ink-3)", font: "inherit", fontSize: 13, fontWeight: 700, cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center", gap: 6, marginTop: 8 }}>
                <Icon.plus size={14} /> Thêm thuộc tính dự án{props.length === 0 ? " — VD: Gói thầu, Hạng mục…" : ""}
              </button>
            )}
            {hiddenSys.length > 0 && (
              <div style={{ marginTop: 12, paddingTop: 12, borderTop: "1px solid var(--line)" }}>
                <div style={{ fontSize: 11, fontWeight: 800, letterSpacing: ".05em", color: "var(--ink-4)", marginBottom: 8 }}>TRƯỜNG MẶC ĐỊNH ĐÃ XÓA</div>
                {hiddenSys.map(f => (
                  <div key={f.id} style={{ display: "flex", alignItems: "center", gap: 11, padding: "7px 10px", margin: "0 -10px", borderRadius: 10, opacity: 0.8 }}>
                    <span style={{ width: 30, height: 30, borderRadius: 9, display: "grid", placeItems: "center", flex: "none", background: "var(--sunken)", color: "var(--ink-4)" }}>{f.icon && window.PropIcon ? React.createElement(window.PropIcon, { name: f.icon, size: 15 }) : <Icon.layers size={15} />}</span>
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ fontWeight: 700, fontSize: 13, color: "var(--ink-3)" }}>{f.name}</div>
                      <div style={{ fontSize: 11, color: "var(--ink-4)", fontWeight: 600, marginTop: 1 }}>Không hiện ở kho, bảng Tài liệu & Tổ chức</div>
                    </div>
                    {isAdmin && <button className="btn sm" style={{ flex: "none" }} onClick={() => restoreSys(f)}><Icon.plus size={13} />&nbsp;Thêm lại</button>}
                  </div>
                ))}
              </div>
            )}
          </div>
          {/* ---- personal pool (owner-only) ---- */}
          <div className="card card-pad">
            <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 6 }}>
              <div className="card-title">Thuộc tính của tôi</div>
              <span style={{ ...tagChip, height: 20, fontSize: 11 }}>{myProps.length}</span>
              <span style={{ ...tagChip, height: 20, fontSize: 10.5, color: "var(--ink-4)", marginLeft: "auto" }}><Icon.eyeOff size={11} />&nbsp;Chỉ mình bạn thấy</span>
            </div>
            <div className="card-sub" style={{ marginBottom: 10 }}>Ghi chú/phân loại riêng của bạn — không ảnh hưởng dữ liệu dự án</div>
            {myProps.map(p => <PropRow key={p.id} p={p} onEdit={setEditMine} onDel={delMine} />)}
            <button onClick={() => setCreatingMine(true)}
              style={{ width: "100%", height: 42, borderRadius: 12, border: "1.5px dashed var(--line)", background: "transparent", color: "var(--ink-3)", font: "inherit", fontSize: 13, fontWeight: 700, cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center", gap: 6, marginTop: myProps.length ? 8 : 0 }}>
              <Icon.plus size={14} /> Thêm thuộc tính của tôi{myProps.length === 0 ? " — VD: Cần xem lại, Ghi chú…" : ""}
            </button>
          </div>
        </div>
        {/* ---- templates ---- */}
        <div className="card card-pad">
          <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", gap: 10, marginBottom: 12 }}>
            <div><div className="card-title">Bộ thuộc tính (Set)</div><div className="card-sub">Áp một set để chọn cột hiển thị ở Documents</div></div>
            {isAdmin && <button className="btn sm" style={{ flex: "none" }} onClick={saveCurrent}><Icon.plus size={13} /> Lưu hiện tại</button>}
          </div>
          <div onClick={allActive ? undefined : showAll} style={{ display: "flex", alignItems: "center", gap: 11, padding: "11px 13px", borderRadius: 12, cursor: allActive ? "default" : "pointer", marginBottom: 8,
            border: `1px solid ${allActive ? "var(--accent)" : "var(--line)"}`, background: allActive ? "var(--accent-soft)" : "var(--surface)" }}>
            <span style={{ width: 34, height: 34, borderRadius: 10, display: "grid", placeItems: "center", flex: "none", background: "var(--accent-soft)", color: "var(--accent)" }}><Icon.layers size={16} /></span>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontWeight: 800, fontSize: 13.5 }}>Tất cả thuộc tính</div>
              <div style={{ fontSize: 11.5, color: "var(--ink-4)", fontWeight: 600, marginTop: 1 }}>Hiển thị mọi cột trong kho</div>
            </div>
            {allActive ? <span className="chip ok" style={{ height: 20, fontSize: 10, flex: "none" }}>Đang dùng</span>
              : (isAdmin && <button className="btn sm" style={{ flex: "none" }} onClick={e => { e.stopPropagation(); showAll(); }}>Dùng</button>)}
          </div>
          {templates.map(t => (
            <div key={t.id} style={{ borderRadius: 12, padding: "11px 13px", marginBottom: 8,
              border: `1px solid ${t.active ? "var(--accent)" : "var(--line)"}`, background: t.active ? "var(--accent-soft)" : "var(--surface)" }}>
              <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                <span style={{ flex: 1, fontWeight: 800, fontSize: 13.5, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{t.name}</span>
                {t.active && <span className="chip ok" style={{ height: 20, fontSize: 10, flex: "none" }}>Đang dùng</span>}
                {!t.active && isAdmin && <button className="btn sm primary" style={{ flex: "none" }} onClick={() => applyT(t)}>Áp</button>}
                {isAdmin && <button className="icon-btn" style={{ width: 28, height: 28, flex: "none" }} title="Sửa set" onClick={() => setEditing(t)}><Icon.pen size={13} /></button>}
                {isAdmin && <button className="icon-btn" style={{ width: 28, height: 28, flex: "none" }} title="Xoá set" onClick={() => delT(t)}><Icon.trash size={13} /></button>}
              </div>
              <div style={{ display: "flex", flexWrap: "wrap", gap: 5, marginTop: 8 }}>
                {t.propertyIds.length === 0 && <span style={{ fontSize: 11.5, color: "var(--ink-4)", fontWeight: 600 }}>Set trống</span>}
                {t.propertyIds.slice(0, 4).map(id => nameOf(id) && <span key={id} style={tagChip}>{nameOf(id)}</span>)}
                {t.propertyIds.length > 4 && <span style={tagChip}>+{t.propertyIds.length - 4}</span>}
              </div>
            </div>
          ))}
          {isAdmin && (
            <button onClick={() => setEditing({ name: "", propertyIds: [] })}
              style={{ width: "100%", height: 42, borderRadius: 12, border: "1.5px dashed var(--line)", background: "transparent", color: "var(--ink-3)", font: "inherit", fontSize: 13, fontWeight: 700, cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center", gap: 6, marginTop: 2 }}>
              <Icon.plus size={14} /> Tạo set mới
            </button>
          )}
        </div>
      </div>
      {creating && <PropModal title="Thuộc tính dự án mới" sub="Mọi thành viên đều thấy — giá trị ghi vào hồ sơ chung" onClose={() => setCreating(false)}>
        <PropertyForm onCreated={() => { reload(); setCreating(false); }} /></PropModal>}
      {editProp && <PropModal title="Sửa thuộc tính dự án" sub={`Đổi tên, kiểu hoặc lựa chọn của "${editProp.name}"`} onClose={() => setEditProp(null)}>
        <PropertyForm prop={editProp} onCreated={() => { reload(); setEditProp(null); }} /></PropModal>}
      {creatingMine && <PropModal title="Thuộc tính của tôi" sub="Chỉ mình bạn thấy — không ảnh hưởng dữ liệu dự án" onClose={() => setCreatingMine(false)}>
        <PropertyForm personal onCreated={() => { reload(); setCreatingMine(false); }} /></PropModal>}
      {editMine && <PropModal title="Sửa thuộc tính của tôi" sub={`Đổi tên, kiểu hoặc lựa chọn của "${editMine.name}"`} onClose={() => setEditMine(null)}>
        <PropertyForm personal prop={editMine} onCreated={() => { reload(); setEditMine(null); }} /></PropModal>}
      {editSys && <PropModal title={`Sửa "${editSys.name}"`}
        sub={editSys.id === "disc" ? "Đổi tên/icon và danh sách lựa chọn — áp cho cả dự án" : "Đổi icon & tên hiển thị — áp cho cả dự án"}
        onClose={() => setEditSys(null)}>
        <SysFieldEditor field={editSys} onSaved={() => setEditSys(null)} /></PropModal>}
      {editing && <TemplateEditor tmpl={editing} props={props} onClose={() => setEditing(null)} onSaved={() => { setEditing(null); reload(); }} />}
    </div>
  );
}

// modal: create/edit a set (name + checkbox selection + up/down order)
function TemplateEditor({ tmpl, props, onClose, onSaved }) {
  const [name, setName] = React.useState(tmpl.name || "");
  const [ids, setIds] = React.useState(tmpl.propertyIds || []);
  const [busy, setBusy] = React.useState(false);
  const toggle = (id) => setIds(a => a.includes(id) ? a.filter(x => x !== id) : [...a, id]);
  const move = (i, d) => setIds(a => { const n = [...a]; const j = i + d; if (j < 0 || j >= n.length) return a; [n[i], n[j]] = [n[j], n[i]]; return n; });
  const chosen = ids.map(id => props.find(p => p.id === id)).filter(Boolean);
  const rest = props.filter(p => !ids.includes(p.id));
  const save = async () => {
    if (!name.trim()) return;
    setBusy(true);
    try {
      if (tmpl.id) await cdeData.updateTemplate(tmpl.id, { name: name.trim(), propertyIds: ids });
      else await cdeData.createTemplate({ name: name.trim(), propertyIds: ids });
      onSaved();
    } catch (e) { window.alert("Lưu set thất bại: " + e.message); }
    finally { setBusy(false); }
  };
  const inp = { width: "100%", height: 38, padding: "0 10px", borderRadius: 8, border: "1px solid var(--line)", background: "var(--surface)", color: "var(--ink)", font: "inherit", fontSize: 13.5, fontWeight: 600, outline: "none" };
  return (
    <div onClick={onClose} style={{ position: "fixed", inset: 0, zIndex: 56, background: "rgba(8,19,23,.5)", backdropFilter: "blur(3px)", display: "grid", placeItems: "center" }}>
      <div onClick={e => e.stopPropagation()} className="card" style={{ width: 460, maxHeight: "90vh", overflowY: "auto", padding: 22, boxShadow: "var(--shadow-lg)" }}>
        <div style={{ fontWeight: 800, fontSize: 16 }}>{tmpl.id ? "Sửa set" : "Tạo set"}</div>
        <input style={{ ...inp, marginTop: 12 }} value={name} onChange={e => setName(e.target.value)} placeholder="Tên set, vd: Bản vẽ kết cấu" />
        <div style={{ fontSize: 11.5, fontWeight: 700, color: "var(--ink-3)", margin: "14px 0 6px" }}>CỘT TRONG SET (theo thứ tự)</div>
        {chosen.length === 0 && <div style={{ fontSize: 12.5, color: "var(--ink-4)" }}>Chưa chọn cột nào.</div>}
        {chosen.map((p, i) => (
          <div key={p.id} style={{ display: "flex", alignItems: "center", gap: 8, padding: "6px 0" }}>
            <span style={{ flex: 1, fontWeight: 600, fontSize: 13 }}>{p.name}</span>
            <button className="icon-btn" style={{ width: 26, height: 26 }} onClick={() => move(i, -1)} disabled={i === 0}>↑</button>
            <button className="icon-btn" style={{ width: 26, height: 26 }} onClick={() => move(i, 1)} disabled={i === chosen.length - 1}>↓</button>
            <button className="icon-btn" style={{ width: 26, height: 26 }} onClick={() => toggle(p.id)}>✕</button>
          </div>
        ))}
        {rest.length > 0 && <div style={{ fontSize: 11.5, fontWeight: 700, color: "var(--ink-3)", margin: "14px 0 6px" }}>THÊM CỘT</div>}
        <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>
          {rest.map(p => <span key={p.id} onClick={() => toggle(p.id)} style={{ cursor: "pointer", height: 26, padding: "0 10px", borderRadius: 99, fontSize: 12, fontWeight: 700, display: "inline-flex", alignItems: "center", background: "var(--sunken)", color: "var(--ink-2)" }}>+ {p.name}</span>)}
        </div>
        <div style={{ display: "flex", justifyContent: "flex-end", gap: 10, marginTop: 18 }}>
          <button className="btn" onClick={onClose}>Huỷ</button>
          <button className="btn primary" disabled={busy || !name.trim()} onClick={save}>{busy ? "Đang lưu…" : "Lưu"}</button>
        </div>
      </div>
    </div>
  );
}

// slug an id from a (possibly Vietnamese) label
function slugId(s) {
  return (s || "").toString().toLowerCase().normalize("NFD").replace(/[̀-ͯ]/g, "")
    .replace(/[đ]/g, "d").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "opt";
}

// edit a system field: display icon + name; and (for Bộ môn) the editable option list.
// Persists to project_settings via saveSysField. disc options drive window.DISC_NAME/DISC_COL.
function SysFieldEditor({ field, onSaved }) {
  const isDisc = field.id === "disc";
  const [name, setName] = React.useState(field.name || "");
  const [icon, setIcon] = React.useState(field.icon || null);
  const [opts, setOpts] = React.useState(() => isDisc && window.discOptions ? window.discOptions().map(o => ({ ...o })) : []);
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState("");
  const IconPicker = window.IconPicker;
  const lbl = { display: "block", fontSize: 11, fontWeight: 800, letterSpacing: ".06em", color: "var(--ink-4)", margin: "14px 0 7px" };
  const inp = { width: "100%", height: 38, padding: "0 10px", borderRadius: 9, border: "1px solid var(--line)", background: "var(--sunken)", color: "var(--ink)", font: "inherit", fontSize: 13.5, fontWeight: 600, outline: "none" };
  const setOpt = (i, patch) => setOpts(a => a.map((o, j) => j === i ? { ...o, ...patch } : o));
  const delOpt = (i) => setOpts(a => a.filter((_, j) => j !== i));
  const addOpt = () => setOpts(a => [...a, { id: "", label: "", color: "#6b7280" }]);
  const save = async () => {
    if (!name.trim()) { setErr("Nhập tên hiển thị"); return; }
    const patch = { name: name.trim(), icon: icon || null };
    if (isDisc) {
      const used = new Set();
      const finalOpts = [];
      for (const o of opts) {
        const label = (o.label || "").trim();
        if (!label) continue;                       // bỏ dòng trống
        let id = o.id;
        if (!id) { const base = slugId(label); id = base; let n = 2; while (used.has(id)) id = base + "-" + (n++); }
        if (used.has(id)) continue;                 // chống trùng id
        used.add(id);
        finalOpts.push({ id, label, color: o.color || "#6b7280" });
      }
      if (!finalOpts.length) { setErr("Cần ít nhất một bộ môn"); return; }
      patch.options = finalOpts;
    }
    setBusy(true); setErr("");
    try { await window.saveSysField(field.id, patch); onSaved(); }
    catch (e) { setErr(e.message || "Lưu thất bại (cần quyền admin)"); }
    finally { setBusy(false); }
  };
  return (
    <div>
      <label style={lbl}>TÊN HIỂN THỊ</label>
      <input style={inp} value={name} onChange={e => setName(e.target.value)} placeholder={field.name} />
      <label style={lbl}>ICON</label>
      {IconPicker ? <IconPicker value={icon} onChange={setIcon} /> : null}
      {isDisc && (
        <React.Fragment>
          <label style={lbl}>LỰA CHỌN BỘ MÔN</label>
          <div style={{ display: "grid", gap: 7 }}>
            {opts.map((o, i) => (
              <div key={i} style={{ display: "flex", alignItems: "center", gap: 8 }}>
                <input type="color" value={o.color || "#6b7280"} onChange={e => setOpt(i, { color: e.target.value })}
                  title="Màu" style={{ width: 34, height: 34, padding: 0, border: "1px solid var(--line)", borderRadius: 8, background: "var(--sunken)", cursor: "pointer", flex: "none" }} />
                <input style={{ ...inp, flex: 1 }} value={o.label} placeholder="Tên bộ môn (vd: Cơ điện)" onChange={e => setOpt(i, { label: e.target.value })} />
                <button className="icon-btn" style={{ width: 30, height: 30, flex: "none" }} title="Xoá" onClick={() => delOpt(i)}><Icon.trash size={13} /></button>
              </div>
            ))}
          </div>
          <button onClick={addOpt} style={{ width: "100%", height: 36, marginTop: 8, borderRadius: 9, border: "1.5px dashed var(--line)", background: "transparent", color: "var(--ink-3)", font: "inherit", fontSize: 12.5, fontWeight: 700, cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center", gap: 6 }}>
            <Icon.plus size={13} /> Thêm bộ môn
          </button>
        </React.Fragment>
      )}
      <div style={{ marginTop: 14, fontSize: 11.5, color: "var(--ink-4)", fontWeight: 500, lineHeight: 1.5 }}>
        {isDisc
          ? <React.Fragment>Danh sách này dùng chung toàn dự án (bảng Tài liệu, RFI, Tổ chức…). Xoá một bộ môn không xoá hồ sơ cũ — hồ sơ đó hiển thị theo mã gốc cho tới khi đổi.</React.Fragment>
          : <React.Fragment>Chỉ đổi cách <b>hiển thị</b> (icon + tên) ở kho, bảng Tài liệu và panel Tổ chức — không đổi giá trị của từng hồ sơ.</React.Fragment>}
      </div>
      {err && <div style={{ marginTop: 10, fontSize: 12, color: "var(--danger)", fontWeight: 600 }}>{err}</div>}
      <button className="btn primary" disabled={busy} style={{ marginTop: 16, width: "100%", justifyContent: "center" }} onClick={save}>
        <Icon.check size={14} /> {busy ? "Đang lưu…" : "Lưu thay đổi"}
      </button>
    </div>
  );
}

window.PropsAdmin = PropsAdmin;
