/* ============================================================
   Users & Roles Management
   ============================================================
   CRUD for system users:
   - Display name, username, password, role, email
   - Audit fields: created by, last edited by + timestamps
   - Role-based color coding (Admin / Supervisor / Staff)
   - Filter by role, search by name/username/email
   ============================================================ */

/* System roles per MTG4 §2.2 — 4-level hierarchy */
const ROLE_META = {
  Admin:      { tone: "danger", desc: "Full system access — manage users, entities, templates, and publish projects." },
  Supervisor: { tone: "warn",   desc: "Create Project Drafts under designated entities; review work papers; can be Project Creator." },
  Staff:      { tone: "",       desc: "Work on assigned WPIDs — upload, edit, mark for review; cannot create projects." },
  Guest:      { tone: "ok",     desc: "Read-only access to assigned projects — for external auditors, regulators, or observers." },
};
const ROLE_OPTIONS = ["Admin", "Supervisor", "Staff", "Guest"];

/* ====== Add / Edit User Modal ====== */
const UserFormModal = ({ initial, existingEmails, onClose, onSave }) => {
  const isEdit = !!initial;
  const [name, setName] = React.useState(initial?.name || "");
  const [password, setPassword] = React.useState("");
  const [showPwd, setShowPwd] = React.useState(false);
  const [role, setRole] = React.useState(initial?.role || "Staff");
  const [email, setEmail] = React.useState(initial?.email || "");
  const [active, setActive] = React.useState(initial?.active !== false);

  /* Validation — email IS the login identifier (replaced username, 2026-06-12) */
  const emailClean = email.trim().toLowerCase();
  const emailValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(emailClean);
  const emailTaken = emailValid
    && existingEmails.includes(emailClean)
    && emailClean !== (initial?.email || "").toLowerCase();
  const passwordValid = isEdit
    ? (password === "" || password.length >= 8)
    : password.length >= 8;
  const canSave = name.trim().length >= 2 && emailValid && !emailTaken && passwordValid;

  const handleSave = () => {
    onSave({
      name: name.trim(),
      email: emailClean,
      /* keep the internal username for legacy seed references — derived from the email */
      username: initial?.username || emailClean.split("@")[0],
      ...(password ? { password: "••••••••" } : {}),
      role,
      active,
    });
  };

  return (
    <div className="modal-veil" onClick={onClose}>
      <div className="modal" onClick={e => e.stopPropagation()} style={{maxWidth:540, width:"94vw"}}>
        <div className="modal-head">
          <div style={{width:32,height:32,borderRadius:8,background:"var(--accent-soft)",color:"var(--accent-ink)",display:"grid",placeItems:"center"}}>
            <Icon n={isEdit ? "edit-3" : "user"} s={16}/>
          </div>
          <h3>{isEdit ? `Edit user — ${initial.name}` : "New user"}</h3>
        </div>
        <div className="modal-body">
          {!isEdit && (
            <div className="banner muted" style={{marginBottom:14}}>
              <div className="b-ico"><Icon n="info" s={14}/></div>
              <div className="b-body">
                <span className="b-title">Audit trail recorded</span>
                Created by you ({CURRENT_ADMIN.name}) at the current time. Future edits are logged automatically.
              </div>
            </div>
          )}

          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:14}}>
            <div className="field">
              <label>Display name <span className="req">*</span></label>
              <input type="text" value={name} onChange={e=>setName(e.target.value)} placeholder="e.g. Sarah Mitchell" autoFocus/>
              <div className="help">Shown in avatars, sign-offs, and activity logs.</div>
            </div>
            <div className="field">
              <label>Email <span className="req">*</span></label>
              <input type="email" value={email} onChange={e=>setEmail(e.target.value)} placeholder="sarah@tumweb.co.th"
                style={!email || (emailValid && !emailTaken) ? undefined : {borderColor:"var(--danger)"}}/>
              {emailTaken && <div className="err"><Icon n="alert" s={11}/> Email already in use</div>}
              {email && !emailValid && <div className="err"><Icon n="alert" s={11}/> Invalid email format</div>}
              {!email && <div className="help">Used to sign in.</div>}
            </div>
          </div>

          <div className="field">
            <label>
              {isEdit ? "New password" : "Password"} {!isEdit && <span className="req">*</span>}
              {isEdit && <span className="muted" style={{fontWeight:400,fontSize:11,marginLeft:6}}>(leave blank to keep current)</span>}
            </label>
            <div style={{display:"flex",gap:6}}>
              <input
                type={showPwd ? "text" : "password"}
                value={password}
                onChange={e=>setPassword(e.target.value)}
                placeholder={isEdit ? "Leave blank to keep current password" : "Min. 8 characters"}
                style={{flex:1, fontFamily:showPwd ? "var(--mono)" : "inherit"}}
              />
              <button className="btn" type="button" onClick={()=>setShowPwd(v=>!v)} title={showPwd ? "Hide" : "Show"} style={{minWidth:42}}>
                <Icon n="eye" s={13}/>
              </button>
            </div>
            {password && password.length < 8 && <div className="err"><Icon n="alert" s={11}/> Must be at least 8 characters</div>}
            {!password && !isEdit && <div className="help">Min. 8 characters. User will be prompted to change on first login.</div>}
          </div>

          <div className="field">
            <label>Role <span className="req">*</span></label>
            <select value={role} onChange={e=>setRole(e.target.value)} title={ROLE_META[role]?.desc}>
              {ROLE_OPTIONS.map(r => (
                <option key={r} value={r} title={ROLE_META[r].desc}>{r}</option>
              ))}
            </select>
            <div className="help" style={{display:"flex",alignItems:"center",gap:6,marginTop:6}}>
              <Icon n="info" s={11}/>
              <span>{ROLE_META[role]?.desc}</span>
            </div>
          </div>

          {isEdit && (
            <div className="field" style={{marginBottom:0}}>
              <label>Account status</label>
              <div style={{display:"flex",gap:8,alignItems:"center",padding:"10px 12px",border:"1px solid var(--line)",borderRadius:"var(--radius)",background:"var(--panel-3)"}}>
                <label style={{display:"flex",alignItems:"center",gap:6,cursor:"pointer"}}>
                  <input type="radio" checked={active} onChange={()=>setActive(true)}/>
                  <span className="sbadge ok" style={{fontSize:11}}><Icon n="check-circle" s={10}/> Active</span>
                </label>
                <label style={{display:"flex",alignItems:"center",gap:6,cursor:"pointer"}}>
                  <input type="radio" checked={!active} onChange={()=>setActive(false)}/>
                  <span className="sbadge archived" style={{fontSize:11}}><Icon n="x-circle" s={10}/> Inactive</span>
                </label>
                <span className="muted" style={{fontSize:11,marginLeft:"auto"}}>Inactive users keep their history but can't sign in.</span>
              </div>
            </div>
          )}
        </div>
        <div className="modal-foot">
          <button className="btn" onClick={onClose}>Cancel</button>
          <button className="btn primary" disabled={!canSave} onClick={handleSave}>
            <Icon n="check" s={13}/> {isEdit ? "Save changes" : "Create user"}
          </button>
        </div>
      </div>
    </div>
  );
};

/* ====== Set Inactive confirmation — MTG4 §2.2 forbids deleting users ====== */
const SetInactiveUserModal = ({ user, onClose, onConfirm }) => {
  return (
    <div className="modal-veil" onClick={onClose}>
      <div className="modal" onClick={e=>e.stopPropagation()}>
        <div className="modal-head">
          <div style={{width:32,height:32,borderRadius:8,background:"var(--warn-soft)",color:"var(--warn-ink)",display:"grid",placeItems:"center"}}>
            <Icon n="x-circle" s={16}/>
          </div>
          <h3>Set user as Inactive?</h3>
        </div>
        <div className="modal-body">
          <p style={{margin:"0 0 12px"}}>
            <b>{user.name}</b> (<span className="mono">{user.email || "@"+user.username}</span>) will be marked <b>Inactive</b> and lose sign-in access. Their historical sign-offs, uploads, and edits remain fully in the audit log.
          </p>
          <div className="banner muted">
            <div className="b-ico"><Icon n="info" s={14}/></div>
            <div className="b-body">
              <span className="b-title">Linked users cannot be deleted</span>
              To preserve audit-trail integrity, accounts with project history are never removed. Re-activate any time with the Status switch.
            </div>
          </div>
        </div>
        <div className="modal-foot">
          <button className="btn" onClick={onClose}>Cancel</button>
          <button className="btn warn solid" onClick={onConfirm}>
            <Icon n="x-circle" s={13}/> Set Inactive
          </button>
        </div>
      </div>
    </div>
  );
};

/* ====== Users Screen ====== */
const UsersScreen = ({ state, nav }) => {
  const [users, setUsers] = React.useState(USERS);
  const [q, setQ] = React.useState("");
  const [roleFilter, setRoleFilter] = React.useState("all");
  const [modal, setModal] = React.useState(null); // {type:'add'} | {type:'edit',user} | {type:'delete',user}

  const counts = {
    all: users.length,
    Admin: users.filter(u => u.role === "Admin").length,
    Supervisor: users.filter(u => u.role === "Supervisor").length,
    Staff: users.filter(u => u.role === "Staff").length,
    Guest: users.filter(u => u.role === "Guest").length,
    inactive: users.filter(u => u.active === false).length,
  };

  /* Sorting — click a column header to toggle asc/desc */
  const [sort, setSort] = React.useState({ k: null, dir: "asc" });
  const SORT_GETTERS = {
    name:     u => u.name,
    role:     u => u.role,
    created:  u => u.createdAt || "",
    lastEdit: u => u.lastEditAt || "",
    status:   u => u.active === false ? 1 : 0,
  };

  const filtered = sortRows(users.filter(u => {
    if (roleFilter !== "all" && u.role !== roleFilter) return false;
    if (q && !`${u.name} ${u.username} ${u.email}`.toLowerCase().includes(q.toLowerCase())) return false;
    return true;
  }), sort, SORT_GETTERS);

  const handleAdd = (payload) => {
    const id = "U-NEW" + String(users.filter(u => u.id.startsWith("U-NEW")).length + 1).padStart(2, "0");
    const now = "2026-06-08T10:00:00";
    const newUser = {
      id, ...payload,
      password: payload.password || "••••••••",
      active: true,
      createdBy: CURRENT_ADMIN.id, createdAt: now,
      lastEditBy: CURRENT_ADMIN.id, lastEditAt: now,
    };
    setUsers(prev => [newUser, ...prev]);
    USERS.unshift(newUser); // also update global so other screens see it
    nav.toast(`User ${payload.name} created`, "ok");
    nav.log && nav.log({ action:"edit", obj:`User ${payload.name}`, detail:`Created user · ${payload.role} · @${payload.username}`, severity:"critical" });
    setModal(null);
  };

  const handleEdit = (id, payload) => {
    const now = "2026-06-08T10:00:00";
    const updates = { ...payload, lastEditBy: CURRENT_ADMIN.id, lastEditAt: now };
    setUsers(prev => prev.map(u => u.id === id ? { ...u, ...updates } : u));
    /* keep global USERS in sync */
    const idx = USERS.findIndex(u => u.id === id);
    if (idx >= 0) USERS[idx] = { ...USERS[idx], ...updates };
    nav.toast(`User ${payload.name} updated`, "ok");
    nav.log && nav.log({ action:"edit", obj:`User ${payload.name}`, detail:`Updated user · ${Object.keys(payload).join(", ")}`, severity:"critical" });
    setModal(null);
  };

  /* Per MTG4 §2.2 — set Inactive instead of delete */
  const handleSetInactive = (id) => {
    const target = users.find(u => u.id === id);
    setUsers(prev => prev.map(u => u.id === id ? {...u, active: false, lastEditBy: CURRENT_ADMIN.id, lastEditAt: "2026-06-08T10:00:00"} : u));
    const idx = USERS.findIndex(u => u.id === id);
    if (idx >= 0) USERS[idx] = {...USERS[idx], active: false};
    nav.toast(`User ${target?.name} set as Inactive`, "warn");
    nav.log && nav.log({ action:"edit", obj:`User ${target?.name}`, detail:`Set user as Inactive · was ${target?.role} · audit trail preserved`, severity:"critical" });
    setModal(null);
  };

  /* Flip an Inactive account straight back to Active (no confirm needed) */
  const handleReactivate = (id) => {
    const target = users.find(u => u.id === id);
    setUsers(prev => prev.map(u => u.id === id ? {...u, active: true, lastEditBy: CURRENT_ADMIN.id, lastEditAt: "2026-06-08T10:00:00"} : u));
    const idx = USERS.findIndex(u => u.id === id);
    if (idx >= 0) USERS[idx] = {...USERS[idx], active: true};
    nav.toast(`User ${target?.name} reactivated`, "ok");
    nav.log && nav.log({ action:"edit", obj:`User ${target?.name}`, detail:`Reactivated user · ${target?.role}`, severity:"critical" });
  };

  /* Plain text (no colored badge) — the role names alone carry enough meaning */
  const roleBadge = (role) => {
    const m = ROLE_META[role] || {};
    return <span title={m.desc} style={{fontSize:12.5}}>{role}</span>;
  };

  return (
    <>
      <div className="page-head">
        <div className="page-title-row">
          <h1 className="page-title">Users &amp; Roles</h1>
          <span className="sbadge">{users.length} total</span>
        </div>
        <div className="page-sub">
          Manage system users — display name, login email, password, role, and full audit trail.
          <b> Users with project history cannot be deleted</b>; set Inactive to revoke access while keeping historical actions intact.
        </div>
        <div style={{marginTop:18, display:"flex", gap:10, flexWrap:"wrap"}}>
          <div className="cnt"><span className="val">{counts.Admin}</span><span className="lbl">Admins</span></div>
          <div className="cnt"><span className="val">{counts.Supervisor}</span><span className="lbl">Supervisors</span></div>
          <div className="cnt"><span className="val">{counts.Staff}</span><span className="lbl">Staff</span></div>
          {counts.Guest > 0 && <div className="cnt"><span className="val">{counts.Guest}</span><span className="lbl">Guests</span></div>}
          {counts.inactive > 0 && <div className="cnt"><span className="val">{counts.inactive}</span><span className="lbl">Inactive</span></div>}
        </div>
      </div>

      <div className="page-body">
        {/* Filter bar */}
        <div className="card" style={{padding:14,marginBottom:14,display:"flex",gap:10,alignItems:"center",flexWrap:"wrap"}}>
          <div className="input" style={{maxWidth:340, flex:1}}>
            <Icon n="search" s={13} c="muted"/>
            <input placeholder="Search by name or email…" value={q} onChange={e=>setQ(e.target.value)}/>
          </div>
          <div style={{display:"flex",gap:4}}>
            <button className={`btn sm ${roleFilter==="all"?"accent":""}`} onClick={()=>setRoleFilter("all")}>All <span className="mono" style={{opacity:.7,marginLeft:3}}>{counts.all}</span></button>
            {ROLE_OPTIONS.map(r => (
              <button key={r} className={`btn sm ${roleFilter===r?"accent":""}`} onClick={()=>setRoleFilter(r)}>
                {r} <span className="mono" style={{opacity:.7,marginLeft:3}}>{counts[r]}</span>
              </button>
            ))}
          </div>
          <span style={{flex:1}}/>
          <button className="btn primary sm" onClick={()=>setModal({type:"add"})}>
            <Icon n="plus" s={12}/> New user
          </button>
        </div>

        {/* Users table */}
        {filtered.length === 0 ? (
          <div className="card">
            <EmptyState
              icon="users"
              title={users.length === 0 ? "No users yet" : "No users match the filters"}
              sub={users.length === 0 ? "Add your first user to get started." : "Try clearing the search or role filter."}
              cta={users.length === 0 && <button className="btn primary" onClick={()=>setModal({type:"add"})}><Icon n="plus" s={13}/> New user</button>}
            />
          </div>
        ) : (
          <div className="card">
            <div className="tbl-wrap"><table className="tbl">
              <thead><tr>
                <SortTh label="User" k="name" sort={sort} setSort={setSort}/>
                <SortTh label="Role" k="role" sort={sort} setSort={setSort}/>
                <SortTh label="Created" k="created" sort={sort} setSort={setSort}/>
                <SortTh label="Last edit" k="lastEdit" sort={sort} setSort={setSort}/>
                <SortTh label="Active" k="status" sort={sort} setSort={setSort} style={{width:120}}/>
                <th style={{width:110, textAlign:"right"}}></th>
              </tr></thead>
              <tbody>
                {filtered.map(u => {
                  const createdBy = userById(u.createdBy);
                  const editedBy = userById(u.lastEditBy);
                  const isMe = u.id === CURRENT_ADMIN.id;
                  /* Hard delete is allowed ONLY while the account has no footprint —
                     not a member/creator of any project, not an entity Project Creator.
                     Covers "created by mistake, delete immediately"; once linked,
                     Inactive is the only way out (audit trail). */
                  const unlinked =
                    !(state.projects || []).some(p => (p.members || []).includes(u.id) || p.createdBy === u.id) &&
                    !(state.entities || []).some(e => (e.creators || []).includes(u.id));
                  return (
                    <tr key={u.id} className={u.active === false ? "muted" : ""}>
                      <td>
                        <div style={{display:"flex",alignItems:"center",gap:10}}>
                          <Avatar id={u.id} name={u.name} size="md"/>
                          <div>
                            <div style={{display:"flex",alignItems:"center",gap:6}}>
                              <span style={{fontWeight:600}}>{u.name}</span>
                              {isMe && <span className="badge accent" style={{fontSize:9.5}}>You</span>}
                            </div>
                            {u.email && <div className="mono" style={{fontSize:10.5,color:"var(--muted)"}}>{u.email}</div>}
                          </div>
                        </div>
                      </td>
                      <td>{roleBadge(u.role)}</td>
                      <td>
                        <div style={{display:"flex",alignItems:"center",gap:6}}>
                          {createdBy && <Avatar id={createdBy.id} name={createdBy.name} size="sm"/>}
                          <div>
                            <div style={{fontSize:11.5}}>{createdBy?.name || "—"}</div>
                            <div className="mono" style={{fontSize:10,color:"var(--muted)"}}>{fmtTsShort(u.createdAt)}</div>
                          </div>
                        </div>
                      </td>
                      <td>
                        <div style={{display:"flex",alignItems:"center",gap:6}}>
                          {editedBy && <Avatar id={editedBy.id} name={editedBy.name} size="sm"/>}
                          <div>
                            <div style={{fontSize:11.5}}>{editedBy?.name || "—"}</div>
                            <div className="mono" style={{fontSize:10,color:"var(--muted)"}}>{fmtTsShort(u.lastEditAt)}</div>
                          </div>
                        </div>
                      </td>
                      <td>
                        {/* Active/Inactive lives here as a switch — turning OFF asks for
                           confirm (audit-relevant), turning ON reactivates instantly */}
                        <button className={`toggle bare ${u.active !== false ? "on" : ""}`}
                          disabled={isMe}
                          style={isMe ? {opacity:.5, cursor:"not-allowed"} : undefined}
                          title={isMe ? "You cannot deactivate your own account" : (u.active !== false ? "Set Inactive — users with project history cannot be deleted" : "Reactivate this account")}
                          onClick={()=>{
                            if (u.active === false) handleReactivate(u.id);
                            else setModal({type:"delete", user:u});
                          }}>
                          <span className="knob"></span>
                        </button>
                      </td>
                      <td style={{textAlign:"right"}}>
                        <div style={{display:"inline-flex",gap:6}}>
                          <button className="btn sm" onClick={()=>setModal({type:"edit", user:u})}>
                            <Icon n="edit-3" s={11}/> Edit
                          </button>
                          {/* Trash is always visible; it is only ENABLED while the
                             account has no footprint (delete-if-created-by-mistake).
                             Linked accounts keep the icon disabled with a tooltip
                             explaining why — set Inactive instead. */}
                          <button className={"btn sm" + (unlinked && !isMe ? " danger" : "")}
                            disabled={!unlinked || isMe}
                            style={!unlinked || isMe ? {opacity:.45, cursor:"not-allowed"} : undefined}
                            title={isMe
                              ? "You cannot delete your own account"
                              : unlinked
                                ? "No project or entity links yet — safe to delete (e.g. created by mistake)"
                                : "Linked to projects/entities — cannot be deleted; set Inactive instead"}
                            onClick={()=>{
                              if (!unlinked || isMe) return;
                              if (!window.confirm(`Delete user "${u.name}" permanently?\n\nThis account has no project or entity links yet, so it can be removed without breaking any audit trail.`)) return;
                              setUsers(prev => prev.filter(x => x.id !== u.id));
                              nav.toast(`User "${u.name}" deleted`, "warn");
                            }}>
                            <Icon n="trash" s={11}/>
                          </button>
                        </div>
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table></div>
          </div>
        )}

      </div>

      {modal?.type === "add" && (
        <UserFormModal
          existingEmails={users.map(u => (u.email||"").toLowerCase())}
          onClose={()=>setModal(null)}
          onSave={handleAdd}
        />
      )}
      {modal?.type === "edit" && (
        <UserFormModal
          initial={modal.user}
          existingEmails={users.map(u => (u.email||"").toLowerCase())}
          onClose={()=>setModal(null)}
          onSave={(payload)=>handleEdit(modal.user.id, payload)}
        />
      )}
      {modal?.type === "delete" && (
        <SetInactiveUserModal user={modal.user} onClose={()=>setModal(null)} onConfirm={()=>handleSetInactive(modal.user.id)}/>
      )}
    </>
  );
};

Object.assign(window, { UsersScreen, UserFormModal, SetInactiveUserModal, ROLE_META, ROLE_OPTIONS });
