/* global React, I, UI */
// =============== ผู้ใช้และสิทธิ์ — ฉบับแก้ไขได้จริง (override window.Users) ===============
const { useState: useStateUP, useEffect: useEffectUP, useMemo: useMemoUP } = React;

// โครงสร้างสิทธิ์แบบละเอียด — กลุ่ม → หน้าย่อย (ผูกกับ NAV key / tab)
const UP_GROUPS = [
  { key: "overview", label: "ภาพรวม", pages: [{ key: "dashboard", label: "แดชบอร์ด" }, { key: "daily-delivery", label: "ส่งของประจำวัน" }] },
  { key: "sales", label: "การขาย", pages: [{ key: "quotations", label: "ใบเสนอราคา" }, { key: "delivery-notes", label: "ใบส่งสินค้า" }, { key: "invoices", label: "ใบแจ้งหนี้" }, { key: "tax-invoices", label: "ใบกำกับภาษี" }, { key: "billing-notes", label: "ใบวางบิล" }, { key: "receipts", label: "ใบเสร็จรับเงิน" }] },
  { key: "purchase", label: "การซื้อ", pages: [{ key: "purchase-orders", label: "ใบสั่งซื้อ" }, { key: "expenses", label: "ค่าใช้จ่าย" }, { key: "payment-vouchers", label: "ใบสำคัญจ่าย" }, { key: "receipt-vouchers", label: "ใบสำคัญรับเงิน" }] },
  { key: "finance", label: "การเงิน", pages: [{ key: "cash-advances", label: "เงินสด" }, { key: "company-cash", label: "บัญชีธนาคาร" }, { key: "bank-accounts", label: "จัดการบัญชีธนาคาร" }] },
  { key: "inventory", label: "คลังสินค้า", pages: [{ key: "inventory", label: "สินค้าและสต็อก" }, { key: "stock-movements", label: "การเคลื่อนไหว" }, { key: "barcode", label: "บาร์โค้ด" }] },
  { key: "time", label: "การลงเวลา", pages: [{ key: "qr-clock", label: "ลงเวลา (สแกน/ขอลา — ของตัวเอง)" }, { key: "qr-records", label: "สรุปลงเวลารายวัน (ทุกคน)" }, { key: "qr-admin", label: "สร้าง QR + กฎบริษัท + อนุมัติลา" }, { key: "my-work", label: "งานของฉัน" }] },
  { key: "payroll", label: "เงินเดือน", pages: [{ key: "payroll", label: "คำนวนเงินเดือน" }, { key: "kpi", label: "KPI ประเมินผล" }] },
  { key: "accounting", label: "บัญชี", pages: [{ key: "cashbook", label: "รายรับรายจ่าย" }, { key: "accounting", label: "บัญชีและภาษี" }, { key: "wht-certs", label: "หนังสือรับรอง 50 ทวิ" }] },
  { key: "people", label: "ผู้คน/CRM", pages: [{ key: "customers", label: "ลูกค้า (CRM)" }, { key: "vendors", label: "Vendor/ผู้ขาย" }, { key: "hr", label: "พนักงาน + HR" }] },
  { key: "projects", label: "โปรเจกต์", pages: [{ key: "projects", label: "โปรเจกต์/Job" }, { key: "activity", label: "กิจกรรมและแชท" }] },
  { key: "system", label: "ระบบ", pages: [{ key: "users", label: "ผู้ใช้และสิทธิ์" }, { key: "settings", label: "ตั้งค่าบริษัท" }, { key: "db-status", label: "การเชื่อมต่อ DB" }] }
];
const UP_MODULES = UP_GROUPS; // เข้ากันได้กับโค้ดเดิม
const UP_PAGE_GROUP = {};
UP_GROUPS.forEach(g => g.pages.forEach(p => UP_PAGE_GROUP[p.key] = g.key));
const UP_LEVELS = ["—", "ดู", "สร้าง", "ทั้งหมด"];

// เติมคีย์สิทธิ์ให้ครบ (รองรับ role เก่าที่มีแค่ 6 โมดูล)
function upNormalizeRole(role) {
  const p = { ...(role.perms || {}) };
  const def = (k, v) => { if (p[k] === undefined) p[k] = v; };
  if (p.system === undefined && p.settings !== undefined) p.system = p.settings;
  const managerial = p.payroll === "ทั้งหมด" || p.accounting === "ทั้งหมด" || p.settings === "ทั้งหมด";
  def("overview", "ดู");
  def("sales", "—"); def("purchase", "—"); def("inventory", "—"); def("payroll", "—"); def("accounting", "—");
  def("finance", p.accounting || "—");
  def("time", managerial ? "ทั้งหมด" : "ดู");
  def("people", p.sales && p.sales !== "—" ? p.sales : "ดู");
  def("projects", "ดู");
  def("system", p.settings !== undefined ? p.settings : "—");
  return { ...role, perms: p };
}

// ===== ตัวแก้สิทธิ์กลาง (ใช้ได้ทั้ง Sidebar / หน้าต่าง ๆ) =====
window.Perms = {
  currentRole() {
    const sess = window.Session ? window.Session.get() : null;
    if (!sess) return null;
    let roles;
    try { roles = JSON.parse(localStorage.getItem("sss-roles") || "null") || window.SSSData.Roles; } catch { roles = window.SSSData.Roles; }
    const r = (roles || []).find(x => x.name === sess.role);
    if (r) return upNormalizeRole(r);
    // ไม่พบบทบาทในระบบ — admin เห็นทั้งหมดเป็นค่าตั้งต้น ส่วนคนอื่นมองไม่เห็น
    if (sess.role === "Admin" || sess.isAdmin) {
      const full = {}; UP_GROUPS.forEach(g => full[g.key] = "ทั้งหมด");
      return { name: sess.role, perms: full };
    }
    return null;
  },
  level(pageKey) {
    const role = this.currentRole();
    if (!role) {
      // ยังไม่ login = เห็นทั้งหมด (พรีวิว/ออกแบบ) · login แล้วแต่ไม่พบบทบาท = ไม่มีสิทธิ์
      return (window.Session && window.Session.get()) ? "—" : "ทั้งหมด";
    }
    const perms = role.perms || {};
    if (perms[pageKey] !== undefined) return perms[pageKey];
    const grp = UP_PAGE_GROUP[pageKey];
    const gl = grp && perms[grp] !== undefined ? perms[grp] : "—";
    if (pageKey === "qr-records" || pageKey === "qr-admin") return gl === "ทั้งหมด" ? "ทั้งหมด" : "—";
    return gl;
  },
  canSee(pageKey) { return this.level(pageKey) !== "—"; },
  groupVisible(groupKey) {
    const g = UP_GROUPS.find(x => x.key === groupKey);
    return g ? g.pages.some(p => this.canSee(p.key)) : true;
  },
  firstVisiblePage() {
    for (const g of UP_GROUPS) for (const p of g.pages) if (this.canSee(p.key) && p.key !== "qr-records" && p.key !== "qr-admin") return p.key;
    return "qr-clock";
  }
};

// ---------- storage ----------
// คืน fallback เมื่อค่าเป็น null หรือ array ว่าง (กัน roles/users ว่างมาบังข้อมูลจริง)
function upLoad(key, fallback) {
  try {
    const v = JSON.parse(localStorage.getItem(key) || "null");
    if (v == null) return fallback;
    if (Array.isArray(v) && v.length === 0) return fallback;
    return v;
  } catch { return fallback; }
}
function upLoadUsers() { return upLoad("sss-users", window.SSSData.Users); }
function upLoadRoles() { return (upLoad("sss-roles", window.SSSData.Roles) || []).map(upNormalizeRole); }
// ✅ โหลดผู้ใช้/บทบาทที่บันทึกไว้เข้า SSSData ตั้งแต่ตอนโหลด — กันการผูกหายตอนรีเฟรช
// ⚠️ override เฉพาะเมื่อไม่ว่าง (กัน array ว่างมาล้าง seed ก่อน sync จะโหลดจริง)
try {
  const _su = JSON.parse(localStorage.getItem("sss-users") || "null");
  if (_su && Array.isArray(_su) && _su.length) window.SSSData.Users = _su;
  const _sr = JSON.parse(localStorage.getItem("sss-roles") || "null");
  if (_sr && Array.isArray(_sr) && _sr.length) window.SSSData.Roles = _sr;
} catch {}
function upSaveUsers(list) {
  localStorage.setItem("sss-users", JSON.stringify(list));
  window.SSSData.Users = list;
  window.dispatchEvent(new Event("sss-users-changed"));
  window.dispatchEvent(new Event("sss-session-changed"));
  // บันทึก Supabase ทันที (ไม่รอ debounce 2s) กัน data loss เมื่อ refresh เร็ว
  setTimeout(() => window.SSSSync && window.SSSSync.save(), 50);
}
function upSaveRoles(list) {
  localStorage.setItem("sss-roles", JSON.stringify(list));
  window.SSSData.Roles = list;
  window.dispatchEvent(new Event("sss-users-changed"));
  setTimeout(() => window.SSSSync && window.SSSSync.save(), 50);
}

function UPPermBadge({ v }) {
  const tone = v === "ทั้งหมด" ? "success" : v === "—" ? "outline" : v === "ดู" ? "info" : "warning";
  return <window.UI.Badge tone={tone}>{v}</window.UI.Badge>;
}

// =============== โปรไฟล์แชท: สี Rank · อิโมจิ · รูปโปรไฟล์ ===============
const UP_RANK_COLORS = [
  { c: "#dc2626", label: "แดง · เจ้าของกิจการ" },
  { c: "#2563eb", label: "ฟ้า · ผู้จัดการ" },
  { c: "#0d9488", label: "เขียวหัวเป็ด · หัวหน้างาน" },
  { c: "#7c3aed", label: "ม่วง · บัญชี" },
  { c: "#ea580c", label: "ส้ม · ช่าง/ผลิต" },
  { c: "#16a34a", label: "เขียว · ขนส่ง" },
  { c: "#db2777", label: "ชมพู · ออกแบบ" },
  { c: "#57534e", label: "เทา · ทั่วไป" }
];
const UP_EMOJIS = ["", "👑", "💼", "🛠️", "⚡", "🎨", "📐", "🧮", "🚚", "⭐", "🔥", "😎", "🤝"];

function upDefaultColor(role) {
  const r = String(role || "");
  if (/เจ้าของ|Admin|บริหาร/.test(r)) return "#dc2626";
  if (/ผู้จัดการ|Manager/.test(r)) return "#2563eb";
  if (/หัวหน้า|Lead/.test(r)) return "#0d9488";
  if (/บัญชี|Account|ธุรการ/.test(r)) return "#7c3aed";
  if (/ขนส่ง|ขับรถ/.test(r)) return "#16a34a";
  if (/ออกแบบ|วิศวกร|Design/.test(r)) return "#db2777";
  if (/ช่าง|ผลิต/.test(r)) return "#ea580c";
  return "#57534e";
}
function upDefaultEmoji(role) {
  const r = String(role || "");
  if (/เจ้าของ|Admin/.test(r)) return "👑";
  if (/ผู้จัดการ|Manager/.test(r)) return "💼";
  if (/หัวหน้า|Lead/.test(r)) return "⭐";
  if (/บัญชี|Account/.test(r)) return "🧮";
  if (/ขนส่ง|ขับรถ/.test(r)) return "🚚";
  if (/ออกแบบ|วิศวกร/.test(r)) return "📐";
  if (/ช่าง/.test(r)) return "🛠️";
  return "";
}
function upLoadProfiles() {
  try { return JSON.parse(localStorage.getItem("sss-profiles") || "{}"); } catch { return {}; }
}
function upSaveProfiles(map) {
  try { localStorage.setItem("sss-profiles", JSON.stringify(map)); } catch {
    window.toast && window.toast("พื้นที่จัดเก็บใกล้เต็ม — รูปโปรไฟล์อาจไม่ถูกบันทึก");
  }
  window.dispatchEvent(new Event("sss-profiles-changed"));
}

window.ChatProfiles = {
  COLORS: UP_RANK_COLORS,
  EMOJIS: UP_EMOJIS,
  roleOf(name) {
    const D = window.SSSData;
    const emp = (D.Employees || []).find(e => e.name === name);
    if (emp) return emp.role;
    const u = (D.Users || []).find(u => u.name === name);
    return u ? u.role : "";
  },
  get(name) {
    const role = this.roleOf(name);
    const p = upLoadProfiles()[name] || {};
    return {
      role,
      color: p.color || upDefaultColor(role),
      emoji: p.emoji !== undefined ? p.emoji : upDefaultEmoji(role),
      avatar: p.avatar || null
    };
  },
  set(name, patch) {
    const map = upLoadProfiles();
    map[name] = { ...(map[name] || {}), ...patch };
    upSaveProfiles(map);
  }
};

// อวตาร์พร้อมสี rank / รูปโปรไฟล์ — ใช้ซ้ำได้ทุกที่
function RankAvatar({ name, size = 28 }) {
  const p = window.ChatProfiles.get(name);
  if (p.avatar) {
    return <img src={p.avatar} alt={name} style={{width: size, height: size, borderRadius: "50%", objectFit: "cover", border: `2px solid ${p.color}`, flexShrink: 0, display: "block"}}/>;
  }
  return (
    <span style={{width: size, height: size, borderRadius: "50%", background: p.color, color: "white", display: "inline-flex", alignItems: "center", justifyContent: "center", fontSize: size * 0.36, fontWeight: 700, flexShrink: 0}}>
      {String(name || "?").slice(0, 2)}
    </span>
  );
}
window.RankAvatar = RankAvatar;

function ChatProfilesTab() {
  const D = window.SSSData;
  const [, force] = useStateUP(0);
  useEffectUP(() => {
    const h = () => force(n => n + 1);
    window.addEventListener("sss-profiles-changed", h);
    return () => window.removeEventListener("sss-profiles-changed", h);
  }, []);

  const extraUsers = (D.Users || []).filter(u => !(D.Employees || []).some(e => e.name === u.name))
    .map(u => ({ id: u.id, name: u.name, role: u.role, dept: "ผู้ใช้ระบบ" }));
  const people = [...D.Employees, ...extraUsers];

  const pickAvatar = async (name, e) => {
    const f = e.target.files[0];
    e.target.value = "";
    if (!f) return;
    const url = window.DeliveryStore ? await window.DeliveryStore.resizeImage(f, 200) : null;
    if (url) { window.ChatProfiles.set(name, { avatar: url }); window.toast && window.toast("อัพเดทรูปโปรไฟล์แล้ว"); }
  };

  return (
    <window.UI.Card title="โปรไฟล์แชท · Rank" sub="สีประจำตำแหน่ง · อิโมจิหลังชื่อ · รูปโปรไฟล์ — แสดงในห้องแชทให้รู้ว่าใครตำแหน่งอะไร">
      <div style={{display: "flex", flexDirection: "column", gap: 8}}>
        {people.map(e => {
          const p = window.ChatProfiles.get(e.name);
          return (
            <div key={e.id} style={{display: "flex", alignItems: "center", gap: 12, padding: "10px 12px", border: "1px solid var(--line)", borderRadius: 10, flexWrap: "wrap"}}>
              <label title="คลิกเพื่อเปลี่ยนรูปโปรไฟล์" style={{cursor: "pointer", position: "relative"}}>
                <input type="file" accept="image/*" style={{display: "none"}} onChange={ev => pickAvatar(e.name, ev)}></input>
                <RankAvatar name={e.name} size={40}/>
                <span style={{position: "absolute", bottom: -3, right: -3, width: 16, height: 16, borderRadius: "50%", background: "var(--surface)", border: "1px solid var(--line-strong)", display: "grid", placeItems: "center"}}><I.camera size={9}/></span>
              </label>
              <div style={{minWidth: 170, flex: 1}}>
                <div style={{fontSize: 13.5, fontWeight: 700, color: p.color}}>{e.name} {p.emoji && <span>{p.emoji}</span>}</div>
                <div style={{fontSize: 11.5, color: "var(--ink-3)"}}>{e.role} · {e.dept}</div>
              </div>
              <div style={{display: "flex", alignItems: "center", gap: 4}} title="สีประจำ Rank">
                {UP_RANK_COLORS.map(rc => (
                  <button key={rc.c} title={rc.label} onClick={() => window.ChatProfiles.set(e.name, { color: rc.c })}
                    style={{width: 20, height: 20, borderRadius: "50%", background: rc.c, cursor: "pointer", padding: 0,
                      border: p.color === rc.c ? "2.5px solid var(--ink-1)" : "2px solid var(--surface)",
                      outline: p.color === rc.c ? "none" : "1px solid var(--line)"}}></button>
                ))}
              </div>
              <select className="input" title="อิโมจิหลังชื่อ" value={p.emoji} onChange={ev => window.ChatProfiles.set(e.name, { emoji: ev.target.value })} style={{width: 76, height: 32, fontSize: 15, textAlign: "center"}}>
                {UP_EMOJIS.map(em => <option key={em || "none"} value={em}>{em || "—"}</option>)}
              </select>
            </div>
          );
        })}
      </div>
    </window.UI.Card>
  );
}

// ---------- แก้ไขสิทธิ์ของบทบาท ----------
function RolePermModal({ role, usersInRole, onClose, onSave, onDelete }) {
  const { Btn, Badge } = window.UI;
  const [name, setName] = useStateUP(role ? role.name : "");
  const [perms, setPerms] = useStateUP(() => upNormalizeRole(role || { perms: {} }).perms);
  const isNew = !role;
  const [openG, setOpenG] = useStateUP({});
  const setGroup = (k, v) => setPerms(p => ({ ...p, [k]: v }));
  const setPage = (pk, v) => setPerms(p => { const n = { ...p }; if (v === "") delete n[pk]; else n[pk] = v; return n; });
  const effPage = (gk, pk) => perms[pk] !== undefined ? perms[pk] : (["qr-records", "qr-admin"].includes(pk) ? (perms[gk] === "ทั้งหมด" ? "ทั้งหมด" : "—") : perms[gk]);

  const save = () => {
    if (!name.trim()) { window.toast && window.toast("กรอกชื่อบทบาท"); return; }
    onSave({ name: name.trim(), perms });
    onClose();
  };

  return (
    <div className="scrim" style={{display: "flex", alignItems: "center", justifyContent: "center", padding: 18, zIndex: 220}} onClick={onClose}>
      <div style={{background: "var(--surface)", borderRadius: 14, width: 620, maxWidth: "96vw", maxHeight: "94vh", display: "flex", flexDirection: "column", overflow: "hidden"}} onClick={e => e.stopPropagation()}>
        <div style={{padding: "16px 20px 12px", borderBottom: "1px solid var(--line)", display: "flex", alignItems: "center", gap: 10}}>
          <div style={{width: 34, height: 34, borderRadius: 8, background: "var(--surface-3)", display: "grid", placeItems: "center"}}><I.shield size={16}/></div>
          <div style={{flex: 1}}>
            <div style={{fontSize: 15, fontWeight: 700}}>{isNew ? "เพิ่มบทบาทใหม่" : `แก้ไขสิทธิ์ — ${role.name}`}</div>
            <div style={{fontSize: 12, color: "var(--ink-3)"}}>
              {usersInRole && usersInRole.length > 0
                ? `มีผลกับ ${usersInRole.length} ผู้ใช้: ${usersInRole.map(u => u.name).join(", ")}`
                : "กำหนดระดับการเข้าถึงของแต่ละโมดูล"}
            </div>
          </div>
          <button className="icon-btn" onClick={onClose}><I.close size={14}/></button>
        </div>

        <div style={{padding: "14px 20px", overflow: "auto", display: "flex", flexDirection: "column", gap: 14}}>
          <div className="field"><label>ชื่อบทบาท</label>
            <input className="input" value={name} onChange={e => setName(e.target.value)} placeholder="เช่น Sales Manager"></input>
          </div>

          <div>
            <div className="label mb">สิทธิ์การเข้าถึงแต่ละเมนู · กดลูกศรเพื่อตั้งสิทธิ์รายหน้าย่อย</div>
            <div style={{display: "flex", flexDirection: "column", gap: 6}}>
              {UP_GROUPS.map(g => {
                const expanded = openG[g.key];
                return (
                <div key={g.key} style={{border: "1px solid var(--line)", borderRadius: 8, background: "var(--surface-2)", overflow: "hidden"}}>
                  <div style={{display: "flex", alignItems: "center", gap: 10, padding: "8px 12px", flexWrap: "wrap"}}>
                    <button className="icon-btn" onClick={() => setOpenG(o => ({ ...o, [g.key]: !o[g.key] }))} title="ตั้งรายหน้าย่อย" style={{width: 22, height: 22}}>{expanded ? <I.chevronUp size={13}/> : <I.chevronDown size={13}/>}</button>
                    <div style={{minWidth: 92, fontSize: 13, fontWeight: 700}}>{g.label}</div>
                    <div style={{display: "flex", gap: 4, flex: 1, flexWrap: "wrap"}}>
                      {UP_LEVELS.map(lv => (
                        <button key={lv} className={`btn sm ${perms[g.key] === lv ? "primary" : ""}`} onClick={() => setGroup(g.key, lv)}>
                          {lv === "—" ? "ไม่มีสิทธิ์" : lv}
                        </button>
                      ))}
                    </div>
                    <span style={{fontSize: 10.5, color: "var(--ink-3)"}}>{g.pages.length} หน้า</span>
                  </div>
                  {expanded && (
                    <div style={{borderTop: "1px dashed var(--line)", padding: "6px 12px 10px 40px", display: "flex", flexDirection: "column", gap: 5}}>
                      {g.pages.map(pg => (
                        <div key={pg.key} style={{display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap"}}>
                          <span style={{flex: 1, minWidth: 150, fontSize: 12.5}}>{pg.label}</span>
                          <select className="input" style={{width: 150, height: 28, fontSize: 12}} value={perms[pg.key] !== undefined ? perms[pg.key] : ""} onChange={e => setPage(pg.key, e.target.value)}>
                            <option value="">≡ ตามกลุ่ม ({effPage(g.key, pg.key) === "—" ? "ไม่มีสิทธิ์" : effPage(g.key, pg.key)})</option>
                            <option value="—">ไม่มีสิทธิ์ (ซ่อนเมนู)</option>
                            <option value="ดู">ดู</option>
                            <option value="สร้าง">สร้าง</option>
                            <option value="ทั้งหมด">ทั้งหมด</option>
                          </select>
                          <span style={{width: 64}}><UPPermBadge v={effPage(g.key, pg.key)}/></span>
                        </div>
                      ))}
                    </div>
                  )}
                </div>
                );
              })}
            </div>
            <div style={{fontSize: 11.5, color: "var(--ink-3)", marginTop: 8, lineHeight: 1.6}}>
              <b>ไม่มีสิทธิ์</b> = มองไม่เห็นเมนู · <b>ดู</b> = เปิดดูอย่างเดียว · <b>สร้าง</b> = เพิ่ม/แก้เอกสารของตัวเอง · <b>ทั้งหมด</b> = เพิ่ม แก้ไข ลบ และอนุมัติได้ · ตั้งระดับหน้าย่อยได้ละเอียด — เช่น ให้ลงเวลาได้แต่ไม่เห็น"สรุปรายวัน"หรือ"สร้าง QR"
            </div>
          </div>
        </div>

        <div style={{padding: "12px 20px", borderTop: "1px solid var(--line)", background: "var(--surface-2)", display: "flex", gap: 8, justifyContent: "space-between"}}>
          <div>
            {!isNew && onDelete && <Btn kind="danger" icon={I.trash} onClick={() => { onDelete(role); onClose(); }}>ลบบทบาท</Btn>}
          </div>
          <div style={{display: "flex", gap: 8}}>
            <Btn kind="ghost" onClick={onClose}>ยกเลิก</Btn>
            <Btn kind="primary" icon={I.check} onClick={save}>บันทึกสิทธิ์</Btn>
          </div>
        </div>
      </div>
    </div>
  );
}

// ---------- เพิ่ม/แก้ไขผู้ใช้ ----------
function UserEditModal({ user, roles, onClose, onSave }) {
  const { Btn } = window.UI;
  const [f, setF] = useStateUP(user || { username: "", name: "", email: "", role: roles[0]?.name || "Admin", password: "", status: "ใช้งานอยู่", empId: "" });
  const upd = (k, v) => setF(p => ({ ...p, [k]: v }));
  const isNew = !user;

  const save = () => {
    if (!f.username.trim() || !f.name.trim()) { window.toast && window.toast("กรอก username และชื่อให้ครบ"); return; }
    if (isNew && !f.password) { window.toast && window.toast("กำหนดรหัสผ่านเริ่มต้น"); return; }
    onSave(f);
    onClose();
  };

  return (
    <div className="scrim" style={{display: "flex", alignItems: "center", justifyContent: "center", padding: 18, zIndex: 220}} onClick={onClose}>
      <div style={{background: "var(--surface)", borderRadius: 14, width: 500, maxWidth: "96vw", maxHeight: "94vh", display: "flex", flexDirection: "column", overflow: "hidden"}} onClick={e => e.stopPropagation()}>
        <div style={{padding: "16px 20px 12px", borderBottom: "1px solid var(--line)", display: "flex", alignItems: "center"}}>
          <div style={{flex: 1, fontSize: 15, fontWeight: 700}}>{isNew ? "เพิ่มผู้ใช้ใหม่" : `แก้ไขผู้ใช้ — ${user.name}`}</div>
          <button className="icon-btn" onClick={onClose}><I.close size={14}/></button>
        </div>
        <div style={{padding: "14px 20px", overflow: "auto", display: "flex", flexDirection: "column", gap: 12}}>
          <div className="field-row cols-2">
            <div className="field"><label>Username</label><input className="input mono" value={f.username} onChange={e => upd("username", e.target.value)} placeholder="เช่น somsak"></input></div>
            <div className="field"><label>{isNew ? "รหัสผ่านเริ่มต้น" : "รหัสผ่านใหม่ (เว้นว่าง = ไม่เปลี่ยน)"}</label><input className="input" type="password" value={f.password || ""} onChange={e => upd("password", e.target.value)} placeholder="••••••••"></input></div>
          </div>
          <div className="field"><label>ชื่อ-นามสกุล</label><input className="input" value={f.name} onChange={e => upd("name", e.target.value)}></input></div>
          <div className="field"><label>อีเมล</label><input className="input" value={f.email} onChange={e => upd("email", e.target.value)} placeholder="name@triplescreative.co.th"></input></div>
          <div className="field"><label>ผูกกับพนักงาน (HR)</label>
            <select className="input" value={f.empId || ""} onChange={e => upd("empId", e.target.value)}>
              <option value="">— ไม่ผูกกับพนักงาน —</option>
              {(window.SSSData.Employees || []).map(e => <option key={e.id} value={e.id}>{e.id} · {e.name} — {e.role}</option>)}
            </select>
            <div style={{fontSize: 11, color: "var(--ink-3)", marginTop: 4}}>ผูกแล้วระบบจะดึงข้อมูลลงเวลา · KPI · ใบสั่งงาน · เงินเดือนของพนักงานคนนี้มาแสดงเมื่อผู้ใช้ login</div>
          </div>
          <div className="field-row cols-2">
            <div className="field"><label>บทบาท (กำหนดสิทธิ์)</label>
              <select className="input" value={f.role} onChange={e => upd("role", e.target.value)}>
                {roles.map(r => <option key={r.name}>{r.name}</option>)}
              </select>
            </div>
            <div className="field"><label>สถานะ</label>
              <select className="input" value={f.status} onChange={e => upd("status", e.target.value)}>
                <option>ใช้งานอยู่</option>
                <option>ระงับการใช้งาน</option>
              </select>
            </div>
          </div>
        </div>
        <div style={{padding: "12px 20px", borderTop: "1px solid var(--line)", background: "var(--surface-2)", display: "flex", gap: 8, justifyContent: "flex-end"}}>
          <Btn kind="ghost" onClick={onClose}>ยกเลิก</Btn>
          <Btn kind="primary" icon={I.check} onClick={save}>{isNew ? "เพิ่มผู้ใช้" : "บันทึก"}</Btn>
        </div>
      </div>
    </div>
  );
}

// ---------- หน้า Users ----------
function UsersPage({ navigate }) {
  const { Btn, Badge, Card, PageHead, Tabs } = window.UI;
  const [tab, setTab] = useStateUP("users");
  const [users, setUsers] = useStateUP(() => upLoadUsers());
  const [roles, setRoles] = useStateUP(() => upLoadRoles());
  const [editUser, setEditUser] = useStateUP(null);     // null | "new" | user
  const [editRole, setEditRole] = useStateUP(null);     // null | "new" | role

  useEffectUP(() => {
    const h = () => { setUsers(upLoadUsers()); setRoles(upLoadRoles()); };
    window.addEventListener("sss-users-changed", h);
    return () => window.removeEventListener("sss-users-changed", h);
  }, []);

  const roleUserCount = (name) => users.filter(u => u.role === name).length;
  const usersInRole = (name) => users.filter(u => u.role === name);

  const saveUser = (f) => {
    let next;
    if (editUser === "new") {
      next = [...users, { ...f, id: "U-" + String(users.length + 1).padStart(3, "0"), lastLogin: "ยังไม่เคยเข้าระบบ" }];
      window.toast && window.toast(`เพิ่มผู้ใช้ ${f.username} แล้ว`);
    } else {
      next = users.map(u => u.id === editUser.id ? { ...u, ...f } : u);
      window.toast && window.toast(`บันทึกข้อมูล ${f.username} แล้ว`);
    }
    setUsers(next); upSaveUsers(next);
    window.logActivity && window.logActivity(editUser === "new" ? "เพิ่มผู้ใช้" : "แก้ไขผู้ใช้", f.username, "users");
  };

  const removeUser = async (u) => {
    const ok = await window.confirmDelete(`ผู้ใช้ ${u.username}`, u.name);
    if (!ok) return;
    const next = users.filter(x => x.id !== u.id);
    setUsers(next); upSaveUsers(next);
  };

  const saveRole = (f) => {
    let next;
    if (editRole === "new") {
      next = [...roles, { ...f, users: 0 }];
      window.toast && window.toast(`เพิ่มบทบาท ${f.name} แล้ว`);
    } else {
      next = roles.map(r => r.name === editRole.name ? { ...r, ...f } : r);
      // ถ้าเปลี่ยนชื่อบทบาท อัพเดทผู้ใช้ที่ถืออยู่ด้วย
      if (f.name !== editRole.name) {
        const nu = users.map(u => u.role === editRole.name ? { ...u, role: f.name } : u);
        setUsers(nu); upSaveUsers(nu);
      }
      window.toast && window.toast(`บันทึกสิทธิ์ ${f.name} แล้ว — มีผลกับ ${roleUserCount(editRole.name)} ผู้ใช้`);
    }
    setRoles(next); upSaveRoles(next);
    window.logActivity && window.logActivity("แก้ไขสิทธิ์บทบาท", f.name, "users");
  };

  const removeRole = async (r) => {
    const inUse = roleUserCount(r.name);
    if (inUse > 0) { window.toast && window.toast(`ลบไม่ได้ — มี ${inUse} ผู้ใช้ถือบทบาทนี้อยู่ ย้ายบทบาทผู้ใช้ก่อน`); return; }
    const next = roles.filter(x => x.name !== r.name);
    setRoles(next); upSaveRoles(next);
    window.toast && window.toast(`ลบบทบาท ${r.name} แล้ว`);
  };

  const openPermOfUser = (u) => {
    const r = roles.find(r => r.name === u.role);
    if (r) setEditRole(r);
    else window.toast && window.toast(`ไม่พบบทบาท "${u.role}" ในระบบ`);
  };

  return (
    <>
      <PageHead title="ผู้ใช้และสิทธิ์การเข้าถึง" sub="จัดการ username · password · บทบาท · สิทธิ์เข้าถึง · ผูกผู้ใช้กับพนักงาน HR — แก้ไขแล้วบันทึกถาวร"
        right={<>
          <Btn icon={I.shield} kind="ghost" onClick={() => setEditRole("new")}>เพิ่มบทบาท</Btn>
          <Btn icon={I.plus} kind="primary" onClick={() => setEditUser("new")}>เพิ่มผู้ใช้</Btn>
        </>}/>

      <Tabs items={[
        { key: "users", label: "ผู้ใช้", count: users.length },
        { key: "roles", label: "บทบาทและสิทธิ์", count: roles.length },
        { key: "profiles", label: "โปรไฟล์แชท · Rank", count: window.SSSData.Employees.length },
        { key: "audit", label: "Audit log" }
      ]} active={tab} onChange={setTab}/>

      {tab === "users" && (
        <Card flush>
          <table className="t">
            <thead><tr><th>Username</th><th>ชื่อ</th><th>บทบาท</th><th>ผูกกับพนักงาน</th><th>เข้าสู่ระบบล่าสุด</th><th>สถานะ</th><th></th></tr></thead>
            <tbody>
              {users.map(u => {
                const linkedEmp = u.empId ? (window.SSSData.Employees || []).find(e => e.id === u.empId) : null;
                const ghostLink = u.empId && !linkedEmp; // ผูก empId ไว้แต่พนักงานถูกลบไปแล้ว
                return (
                <tr key={u.id}>
                  <td className="mono">{u.username}</td>
                  <td>{u.name}<div className="muted" style={{fontSize: 10.5}}>{u.email}</div></td>
                  <td><Badge tone="info">{u.role}</Badge></td>
                  <td>{linkedEmp ? (
                    <span style={{display: "inline-flex", alignItems: "center", gap: 7}}>
                      <RankAvatar name={linkedEmp.name} size={22}/>
                      <span style={{fontSize: 12.5}}>{linkedEmp.name}</span>
                      <span className="mono" style={{fontSize: 10, color: "var(--ink-3)"}}>{linkedEmp.id}</span>
                    </span>
                  ) : ghostLink ? (
                    <span style={{display: "inline-flex", alignItems: "center", gap: 6}}>
                      <Badge tone="danger">พนักงานถูกลบ</Badge>
                      <button className="badge outline" style={{cursor: "pointer", fontSize: 11}} onClick={() => { const next = users.map(x => x.id === u.id ? { ...x, empId: "" } : x); setUsers(next); upSaveUsers(next); window.toast && window.toast("ล้างการผูกพนักงานที่ถูกลบแล้ว"); }}>ล้างการผูก</button>
                    </span>
                  ) : <span className="muted" style={{fontSize: 11.5}}>ไม่ได้ผูก — กด "แก้ไข" เพื่อผูก</span>}</td>
                  <td className="muted">{u.lastLogin}</td>
                  <td><Badge tone={u.status === "ระงับการใช้งาน" ? "danger" : "success"} dot>{u.status || "ใช้งานอยู่"}</Badge></td>
                  <td>
                    <div style={{display: "flex", gap: 4, justifyContent: "flex-end"}}>
                      <Btn size="sm" kind="ghost" icon={I.edit} title="แก้ไขผู้ใช้" onClick={() => setEditUser(u)}>แก้ไข</Btn>
                      <Btn size="sm" kind="ghost" icon={I.shield} title="แก้ไขสิทธิ์ของบทบาทนี้" onClick={() => openPermOfUser(u)}>สิทธิ์</Btn>
                      <button className="icon-btn" title="ลบผู้ใช้" onClick={() => removeUser(u)}><I.trash size={13}/></button>
                    </div>
                  </td>
                </tr>
                );
              })}
            </tbody>
          </table>
        </Card>
      )}

      {tab === "roles" && (
        <Card flush>
          <table className="t">
            <thead><tr><th>บทบาท</th><th className="right">ผู้ใช้</th><th>สิทธิ์การเข้าถึง (สรุปรายกลุ่ม)</th><th></th></tr></thead>
            <tbody>
              {roles.map(r => {
                const nr = upNormalizeRole(r);
                return (
                <tr key={r.name}>
                  <td><b>{r.name}</b></td>
                  <td className="right">{roleUserCount(r.name)}</td>
                  <td>
                    <div style={{display: "flex", gap: 4, flexWrap: "wrap"}}>
                      {UP_GROUPS.filter(g => (nr.perms[g.key] || "—") !== "—").map(g => (
                        <span key={g.key} className="badge" style={{fontSize: 11}}>{g.label}: {nr.perms[g.key]}</span>
                      ))}
                      {UP_GROUPS.every(g => (nr.perms[g.key] || "—") === "—") && <span className="muted" style={{fontSize: 11.5}}>— ไม่มีสิทธิ์ —</span>}
                    </div>
                  </td>
                  <td>
                    <div style={{display: "flex", gap: 4, justifyContent: "flex-end"}}>
                      <Btn size="sm" kind="ghost" icon={I.edit} onClick={() => setEditRole(r)}>แก้ไขสิทธิ์</Btn>
                    </div>
                  </td>
                </tr>
                );
              })}
            </tbody>
          </table>
        </Card>
      )}

      {tab === "profiles" && <ChatProfilesTab/>}

      {tab === "audit" && (
        <Card flush>
          <table className="t">
            <thead><tr><th>เวลา</th><th>ผู้ใช้</th><th>การกระทำ</th><th>IP</th></tr></thead>
            <tbody>
              <tr><td className="mono" style={{fontSize: 12}}>22/05/26 09:12</td><td>piya</td><td>เข้าสู่ระบบ</td><td className="mono" style={{fontSize: 12}}>192.168.1.20</td></tr>
              <tr><td className="mono" style={{fontSize: 12}}>22/05/26 09:05</td><td>nanthaporn</td><td>สร้างใบเสนอราคา QO-2569-0117</td><td className="mono" style={{fontSize: 12}}>192.168.1.45</td></tr>
              <tr><td className="mono" style={{fontSize: 12}}>22/05/26 08:32</td><td>duangjai</td><td>แก้ไขสินค้า SS304-SH-1.5 · เปลี่ยนต้นทุน</td><td className="mono" style={{fontSize: 12}}>192.168.1.32</td></tr>
              <tr><td className="mono" style={{fontSize: 12}}>21/05/26 17:42</td><td>wanpen</td><td>ยื่น ภ.ง.ด.1 เม.ย. 2569 ทาง e-filing</td><td className="mono" style={{fontSize: 12}}>192.168.1.31</td></tr>
              <tr><td className="mono" style={{fontSize: 12}}>21/05/26 14:00</td><td>piya</td><td>อนุมัติ PO-2569-0097 (฿380,000)</td><td className="mono" style={{fontSize: 12}}>192.168.1.20</td></tr>
            </tbody>
          </table>
        </Card>
      )}

      {editUser && <UserEditModal user={editUser === "new" ? null : editUser} roles={roles} onClose={() => setEditUser(null)} onSave={saveUser}/>}
      {editRole && <RolePermModal role={editRole === "new" ? null : editRole} usersInRole={editRole === "new" ? [] : usersInRole(editRole.name)} onClose={() => setEditRole(null)} onSave={saveRole} onDelete={removeRole}/>}
    </>
  );
}

// Override หน้าเดิม (mock) ด้วยฉบับแก้ไขได้จริง
window.Users = UsersPage;
