// ELS HRM — Module 04: Quản Lý Vai Trò Người Dùng (multi-role RBAC) — Tailwind utility classes
// Một user mang NHIỀU vai trò: đúng 1 "vai trò chính" + 0..n "vai trò phụ".
// Quản lý vai trò tập trung tại đây — KHÔNG còn ô chọn vai trò đơn lẻ trong form sửa.

// ─── Role catalog — displayName + mô tả ──────────────────────────────────────
const UM_ROLE_CATALOG = [
  { key: 'admin',          name: 'Admin',          level: 100, icon: 'shield',     desc: 'Toàn quyền hệ thống: cấu hình, phân quyền, quản trị tài khoản.' },
  { key: 'hr_manager',     name: 'HR Manager',     level: 70,  icon: 'users',      desc: 'Quản lý dữ liệu nhân viên xuyên phòng ban. Phê duyệt nghỉ phép, xem toàn bộ hồ sơ.' },
  { key: 'dept_manager',   name: 'Dept. Manager',  level: 50,  icon: 'briefcase',  desc: 'Quản lý nhân viên trong phòng ban, duyệt đơn của nhân viên trực thuộc.' },
  { key: 'employee',       name: 'Employee',       level: 10,  icon: 'user',       desc: 'Quyền cơ bản: xem hồ sơ cá nhân, gửi đơn nghỉ phép, chấm công.' },
  { key: 'payroll_officer',name: 'Payroll Officer',level: 60,  icon: 'dollar',     desc: 'Xử lý bảng lương, phụ cấp và khấu trừ cho toàn công ty.' },
  { key: 'recruiter',      name: 'Recruiter',      level: 40,  icon: 'user-check', desc: 'Quản lý tin tuyển dụng, ứng viên và lịch phỏng vấn.' },
  { key: 'auditor',        name: 'Auditor',        level: 55,  icon: 'eye',        desc: 'Truy cập chỉ-đọc nhật ký kiểm toán và báo cáo tuân thủ.' }
];
const roleMeta = (key) => UM_ROLE_CATALOG.find((r) => r.key === key) || { key, name: key, icon: 'user', desc: '' };

// Cấp độ cao nhất của NGƯỜI ĐANG GÁN (demo: HR Manager = 70).
// Quy tắc trần khi gán: chỉ gán được vai trò có level < CURRENT_ACTOR_LEVEL (không ngoại lệ).
const CURRENT_ACTOR_LEVEL = 70;

// ─── Dữ liệu vai trò được gán theo user ──────────────────────────────────────
// primary: true → vai trò chính (đúng 1). by: người gán. at: thời điểm gán.
const UM_USER_ROLES = {
  // Nguyễn Thị Lan — nhiều vai trò (1 chính + 2 phụ)
  2: [
    { key: 'hr_manager',   primary: true,  at: '01/03/2024 09:05', by: 'Hồ Văn Minh' },
    { key: 'dept_manager', primary: false, at: '15/08/2025 14:20', by: 'Hồ Văn Minh' },
    { key: 'employee',     primary: false, at: '01/03/2024 09:05', by: 'Hệ thống' }
  ],
  // Lê Thị Phương — chỉ 1 vai trò (đó chính là vai trò chính)
  4: [
    { key: 'employee',     primary: true,  at: '12/01/2025 10:30', by: 'Nguyễn Thị Lan' }
  ],
  // Võ Thị Thu — chưa có vai trò nào (empty state)
  6: []
};

// ─── RoleCell — hiển thị vai trò chính + chỉ báo "+N" (bảng & header) ─────────
const RoleCell = ({ role, variant = 'neutral', extra = 0, title }) =>
  <span className="inline-flex items-center gap-[5px] align-middle" title={title}>
    <Badge variant={variant}>{role}</Badge>
    {extra > 0 &&
      <span className="whitespace-nowrap rounded-full border border-border bg-muted px-1.5 py-[3px] text-2xs font-semibold leading-none text-muted-foreground">+{extra}</span>}
  </span>;

// ─── RoleRow — một dòng vai trò trong khu quản lý ────────────────────────────
const UMRoleRow = ({ r, onSetPrimary, onTryRemovePrimary, onRemove, danger = false }) => {
  const m = roleMeta(r.key);
  return (
    <div className={"mb-2.5 flex items-start gap-3 rounded-md border p-3.5 "
      + (danger ? "border-destructive bg-destructive-soft" : (r.primary ? "border-border bg-primary-soft" : "border-border bg-card"))}>
      <div className={"grid size-9 shrink-0 place-items-center rounded-md " + (r.primary ? "bg-primary" : "bg-muted")}>
        <Icon name={m.icon} size={16} style={{ color: r.primary ? '#fff' : 'var(--color-muted-foreground)' }} />
      </div>
      <div className="min-w-0 flex-1">
        <div className="flex flex-wrap items-center gap-2">
          <span className="text-base font-semibold">{m.name}</span>
          {r.primary && <Badge variant="solid-primary">Chính</Badge>}
        </div>
        <div className="mt-[3px] text-xs leading-[1.45] text-muted-foreground">{m.desc}</div>
        <div className="mt-[7px] flex items-center gap-[5px] text-2xs text-muted-foreground">
          <Icon name="clock" size={11} />
          <span>Gán lúc {r.at} bởi <strong className="font-semibold text-foreground">{r.by}</strong></span>
        </div>
      </div>
      <div className="flex shrink-0 items-center gap-1">
        {r.primary ?
          <span className="inline-flex items-center gap-1 whitespace-nowrap px-1 text-2xs text-muted-foreground">
            <Icon name="lock" size={12} /> Không thể gỡ
          </span>
          :
          <>
            <Btn variant="ghost" size="sm" icon="arrow-up" onClick={onSetPrimary}>Đặt làm chính</Btn>
            <Btn variant="ghost" size="sm" iconOnly icon="trash" onClick={onRemove} title="Gỡ vai trò" />
          </>}
      </div>
    </div>
  );
};

// ─── Khu quản lý vai trò (tab "Vai trò") — NƠI DUY NHẤT quản lý vai trò ───────
const UMRoleManager = ({ name, roles, onAssignClick, error, onToggleError }) => {
  const hasRoles = roles.length > 0;
  return (
    <div>
      {/* Trạng thái lỗi: cố gỡ vai trò chính */}
      {error &&
        <div className="mb-3.5 flex gap-2.5 rounded-md border border-destructive bg-destructive-soft px-3.5 py-[11px]">
          <Icon name="alert-circle" size={16} className="mt-px shrink-0 text-destructive" />
          <div className="flex-1">
            <div className="text-sm font-semibold text-destructive">Không thể gỡ vai trò chính</div>
            <div className="mt-0.5 text-xs leading-[1.45] text-destructive opacity-[0.92]">
              Hãy đổi vai trò chính trước — chọn <strong>Đặt làm chính</strong> trên một vai trò phụ, sau đó mới có thể gỡ vai trò này. User luôn phải có đúng một vai trò chính.
            </div>
          </div>
          {onToggleError && <Btn variant="ghost" size="sm" iconOnly icon="x" onClick={onToggleError} title="Đóng" />}
        </div>}

      <div className="mb-3.5 flex items-center justify-between">
        <div>
          <div className="text-base font-semibold">
            {hasRoles ? `Vai trò được gán (${roles.length})` : 'Vai trò được gán'}
          </div>
          <div className="mt-0.5 text-xs text-muted-foreground">
            Quyền thực tế là hợp của tất cả vai trò. Vai trò chính là vai trò đại diện.
          </div>
        </div>
        <Btn variant="soft" size="sm" icon="plus" onClick={onAssignClick}>Gán thêm vai trò</Btn>
      </div>

      {hasRoles ?
        <>
          {/* Vai trò chính lên đầu, rồi tới các vai trò phụ */}
          {[...roles].sort((a, b) => (b.primary ? 1 : 0) - (a.primary ? 1 : 0)).map((r, i) =>
            <UMRoleRow key={r.key} r={r}
              danger={error && r.primary}
              onSetPrimary={() => {}}
              onRemove={r.primary ? undefined : () => {}} />
          )}

          {/* Phạm vi truy cập theo vai trò chính */}
          {(() => {
            const primary = roles.find((r) => r.primary);
            const pm = primary ? roleMeta(primary.key) : null;
            return (
              <div className="mt-3.5 rounded-md bg-muted px-3.5 py-3 text-xs leading-[1.5] text-muted-foreground">
                <strong className="text-foreground">Phạm vi truy cập (hợp của {roles.length} vai trò):</strong> Toàn bộ nhân viên · Tất cả phòng ban · Phê duyệt: Nghỉ phép + Timesheet
                <div className="mt-[7px] flex items-start gap-1.5">
                  <Icon name="help-circle" size={12} className="mt-0.5 shrink-0" />
                  <span>Vai trò chính (<strong className="text-foreground">{pm ? pm.name : '—'}</strong>) không thể gỡ trực tiếp. Để đổi, chọn <strong>Đặt làm chính</strong> trên một vai trò phụ — vai trò chính cũ sẽ tự chuyển thành phụ.</span>
                </div>
              </div>
            );
          })()}
        </>
        :
        /* Empty state — user chưa có vai trò nào */
        <div className="flex flex-col items-center justify-center rounded-md border border-dashed border-border px-6 py-10 text-center">
          <div className="mb-3.5 grid size-[52px] place-items-center rounded-full bg-warning-soft">
            <Icon name="shield" size={24} style={{ color: 'oklch(0.55 0.158 65)' }} />
          </div>
          <div className="mb-1.5 text-base font-semibold">Chưa được gán vai trò nào</div>
          <div className="mb-[18px] max-w-[380px] text-sm leading-[1.6] text-muted-foreground">
            {name} chưa có quyền truy cập hệ thống. Gán ít nhất một vai trò — vai trò đầu tiên sẽ tự động trở thành <strong>vai trò chính</strong>.
          </div>
          <Btn variant="primary" size="sm" icon="plus" onClick={onAssignClick}>Gán vai trò đầu tiên</Btn>
        </div>}
    </div>
  );
};

// ─── Dialog: Gán thêm vai trò (multi-select + chọn vai trò chính) ────────────
const UMAssignRoleDialog = ({ name, currentRoles, onClose, initialSelected = [] }) => {
  const currentKeys = currentRoles.map((r) => r.key);
  const currentPrimary = (currentRoles.find((r) => r.primary) || {}).key || null;
  const available = UM_ROLE_CATALOG.filter((r) => !currentKeys.includes(r.key));

  const [q, setQ] = React.useState('');
  const [selected, setSelected] = React.useState(new Set(initialSelected));
  const [primary, setPrimary] = React.useState(currentPrimary);

  const toggle = (key) => setSelected((prev) => {
    const n = new Set(prev);
    if (n.has(key)) { n.delete(key); if (primary === key) setPrimary(currentPrimary); }
    else n.add(key);
    return n;
  });

  const shown = available.filter((r) => r.name.toLowerCase().includes(q.toLowerCase()));
  // Vai trò chính chọn được = vai trò hiện có + vừa tích chọn
  const primaryOptions = [...currentRoles.map((r) => r.key), ...[...selected]];

  return (
    <div className="absolute inset-0 z-50 grid place-items-center bg-black/50" onClick={onClose}>
      <div onClick={(e) => e.stopPropagation()}
        className="flex max-h-[88%] w-[560px] max-w-[92%] flex-col rounded-lg bg-popover shadow-2xl outline outline-4 outline-[oklch(0.92_0_0_/_0.6)]">
        {/* Header */}
        <div className="flex items-start justify-between border-b border-border px-[22px] pb-3.5 pt-[18px]">
          <div>
            <div className="text-md font-bold">Gán thêm vai trò</div>
            <div className="mt-[3px] text-xs text-muted-foreground">
              Cho người dùng <strong className="text-foreground">{name}</strong> · chỉ hiện vai trò chưa được gán
            </div>
            <div className="mt-1.5 inline-flex items-center gap-1.5 rounded-md bg-muted px-2 py-1 text-2xs text-muted-foreground">
              <Icon name="shield" size={11} style={{ color:'var(--color-muted-foreground)' }} />
              Bạn đang đăng nhập: <strong className="text-foreground">HR Manager (cấp {CURRENT_ACTOR_LEVEL})</strong> — chỉ gán được vai trò cấp dưới {CURRENT_ACTOR_LEVEL}.
            </div>
          </div>
          <Btn variant="ghost" size="sm" iconOnly icon="x" onClick={onClose} />
        </div>

        {/* Body */}
        <div className="flex-1 overflow-y-auto px-[22px] py-4">
          {/* 1 · Chọn vai trò (multi-select) */}
          <div className="mb-2 flex items-center gap-1.5 text-xs font-semibold">
            <span className="grid size-[18px] place-items-center rounded-full bg-primary-soft text-[10px] font-bold text-primary">1</span>
            Chọn vai trò để gán {selected.size > 0 && <span className="font-semibold text-primary">· đã chọn {selected.size}</span>}
          </div>
          <div className="relative mb-2.5 flex items-center">
            <Icon name="search" size={13} className="pointer-events-none absolute left-2.5 size-3.5 text-muted-foreground" />
            <input className="h-8 w-full rounded-md border border-input bg-transparent pl-8 pr-3 text-xs text-foreground shadow-xs transition-colors placeholder:text-muted-foreground focus:border-primary focus:outline-none focus:ring-[3px] focus:ring-ring" placeholder="Tìm vai trò..." value={q} onChange={(e) => setQ(e.target.value)} />
          </div>
          <div className="mb-[18px] flex flex-col gap-1.5">
            {shown.length === 0 &&
              <div className="p-4 text-center text-xs text-muted-foreground">Không còn vai trò nào để gán.</div>}
            {shown.map((r) => {
              const blocked = r.level >= CURRENT_ACTOR_LEVEL;
              const on = selected.has(r.key);
              if (blocked) {
                return (
                  <div key={r.key} title="Vai trò ngang hoặc cao hơn cấp của bạn — không thể gán"
                    className="flex items-start gap-2.5 rounded-md border border-border bg-muted px-[11px] py-[9px] opacity-70">
                    <div className="mt-0.5 grid size-[15px] shrink-0 place-items-center rounded-sm bg-border">
                      <Icon name="lock" size={10} style={{ color: 'var(--color-muted-foreground)' }} />
                    </div>
                    <div className="min-w-0 flex-1">
                      <div className="flex items-center gap-1.5">
                        <span className="text-sm font-semibold text-muted-foreground">{r.name}</span>
                        <span className="rounded-full border border-border bg-card px-1.5 py-px text-2xs font-semibold tabular-nums text-muted-foreground">cấp {r.level}</span>
                      </div>
                      <div className="mt-px text-xs leading-[1.4] text-muted-foreground">{r.level > CURRENT_ACTOR_LEVEL ? 'Cao hơn' : 'Ngang'} cấp của bạn — không thể gán.</div>
                    </div>
                  </div>
                );
              }
              return (
                <label key={r.key}
                  className={"flex cursor-pointer items-start gap-2.5 rounded-md border px-[11px] py-[9px] " + (on ? "border-primary bg-primary-soft" : "border-border bg-card")}>
                  <input type="checkbox" checked={on} onChange={() => toggle(r.key)} className="mt-0.5 size-[15px] shrink-0" style={{ accentColor: 'var(--color-primary)' }} />
                  <div className="min-w-0 flex-1">
                    <div className="flex items-center gap-1.5">
                      <span className="text-sm font-semibold">{r.name}</span>
                      <span className="rounded-full border border-border bg-muted px-1.5 py-px text-2xs font-semibold tabular-nums text-muted-foreground">cấp {r.level}</span>
                    </div>
                    <div className="mt-px text-xs leading-[1.4] text-muted-foreground">{r.desc}</div>
                  </div>
                </label>
              );
            })}
          </div>

          {/* 2 · Chọn vai trò chính */}
          <div className="mb-2 flex items-center gap-1.5 text-xs font-semibold">
            <span className="grid size-[18px] place-items-center rounded-full bg-primary-soft text-[10px] font-bold text-primary">2</span>
            Vai trò chính
          </div>
          <div className="mb-[18px] flex flex-col gap-1">
            {primaryOptions.map((key) => {
              const m = roleMeta(key);
              const on = primary === key;
              const isCurrent = key === currentPrimary;
              return (
                <label key={key} className={"flex cursor-pointer items-center gap-[9px] rounded-sm px-2.5 py-[7px] " + (on ? "bg-muted" : "bg-transparent")}>
                  <input type="radio" name="primary-role" checked={on} onChange={() => setPrimary(key)} className="size-[15px]" style={{ accentColor: 'var(--color-primary)' }} />
                  <span className={"text-sm " + (on ? "font-semibold" : "font-medium")}>{m.name}</span>
                  {isCurrent && <span className="text-2xs text-muted-foreground">(hiện tại)</span>}
                  {!currentRoles.some((r) => r.key === key) && <Badge variant="primary">Mới</Badge>}
                </label>
              );
            })}
          </div>

          {/* 3 · Lý do gán */}
          <div className="mb-1.5 text-xs font-semibold">
            Lý do gán <span className="font-normal text-muted-foreground">(tùy chọn)</span>
          </div>
          <textarea rows={2} placeholder="vd: Kiêm nhiệm quản lý phòng ban từ Q3/2026..." className="w-full resize-none rounded-md border border-input bg-transparent px-[11px] py-2 text-base leading-[1.5] text-foreground shadow-xs transition-colors placeholder:text-muted-foreground focus:border-primary focus:outline-none focus:ring-[3px] focus:ring-ring" />
        </div>

        {/* Footer */}
        <div className="flex items-center justify-between border-t border-border px-[22px] py-3">
          <span className="text-xs text-muted-foreground">
            {selected.size > 0 ? `Sẽ gán thêm ${selected.size} vai trò` : 'Chưa chọn vai trò nào'}
          </span>
          <div className="flex gap-2">
            <Btn variant="outline" size="sm" onClick={onClose}>Hủy</Btn>
            <Btn variant="primary" size="sm" icon="check" onClick={onClose}>Lưu</Btn>
          </div>
        </div>
      </div>
    </div>
  );
};

// ─── Dialog: Đặt lại mật khẩu (admin reset — SRS §5.3) ───────────────────────
// Admin reset: hệ thống sinh MK tạm, KHÔNG hiển thị; buộc đổi lần đầu; kết thúc
// mọi phiên; reset failed_attempts; ghi audit. Admin không xem được MK sau khi sinh.
const UMResetPasswordDialog = ({ name, sessions = 2, onClose, done = false }) => {
  const [ok, setOk] = React.useState(done);

  return (
    <div className="absolute inset-0 z-[60] grid place-items-center bg-black/50" onClick={onClose}>
      <div onClick={(e) => e.stopPropagation()}
        className="flex max-h-[90%] w-[480px] max-w-[92%] flex-col rounded-lg bg-popover shadow-2xl outline outline-4 outline-[oklch(0.92_0_0_/_0.6)]">
        {!ok ?
          <>
            {/* Header */}
            <div className="flex items-start justify-between border-b border-border px-[22px] pb-3.5 pt-[18px]">
              <div className="flex gap-[11px]">
                <div className="grid size-[34px] shrink-0 place-items-center rounded-md bg-warning-soft">
                  <Icon name="settings" size={17} style={{ color: 'oklch(0.55 0.158 65)' }} />
                </div>
                <div>
                  <div className="text-md font-bold">Đặt lại mật khẩu</div>
                  <div className="mt-[3px] text-xs text-muted-foreground">
                    Cho người dùng <strong className="text-foreground">{name}</strong>
                  </div>
                </div>
              </div>
              <Btn variant="ghost" size="sm" iconOnly icon="x" onClick={onClose} />
            </div>

            {/* Body */}
            <div className="flex-1 overflow-y-auto px-[22px] py-4">
              {/* Hệ quả */}
              <div className="mb-[18px] rounded-md bg-warning-soft px-3.5 py-3">
                <div className="mb-2 flex gap-2">
                  <Icon name="alert-circle" size={14} className="mt-px shrink-0" style={{ color: 'oklch(0.55 0.158 65)' }} />
                  <div className="text-sm font-semibold" style={{ color: 'oklch(0.5 0.158 65)' }}>Thao tác này sẽ:</div>
                </div>
                {[
                  'Sinh mật khẩu mới và gửi qua email cho người dùng. Vì bảo mật, mật khẩu không hiển thị và bạn không thể xem.',
                  'Buộc người dùng đổi mật khẩu ở lần đăng nhập kế tiếp.',
                  `Kết thúc ngay ${sessions} phiên đang đăng nhập của người dùng.`,
                  'Đặt lại bộ đếm đăng nhập thất bại về 0.'
                ].map((t, i) =>
                  <div key={i} className={"flex gap-[7px] pl-[22px] text-xs leading-[1.45] " + (i ? "mt-[5px]" : "")} style={{ color: 'oklch(0.45 0.09 65)' }}>
                    <span className="mt-1.5 size-1 shrink-0 rounded-full bg-current" />
                    <span>{t}</span>
                  </div>
                )}
              </div>

              {/* Kênh gửi — chỉ qua email */}
              <div className="mb-2 text-xs font-semibold">Gửi mật khẩu mới qua</div>
              <div className="mb-[18px] flex items-center gap-[9px] rounded-md border border-border bg-muted px-3 py-2.5">
                <Icon name="mail" size={15} className="shrink-0 text-muted-foreground" />
                <div className="flex-1">
                  <div className="text-sm font-medium">Email người dùng</div>
                  <div className="mt-px text-2xs text-muted-foreground">Mật khẩu mới chỉ được gửi qua email — bạn sẽ không xem được.</div>
                </div>
              </div>

              {/* Lý do */}
              <div className="mb-1.5 text-xs font-semibold">
                Lý do <span className="font-normal text-muted-foreground">(tùy chọn)</span>
              </div>
              <textarea rows={2} placeholder="vd: Người dùng quên mật khẩu, yêu cầu qua ticket #4821..." className="w-full resize-none rounded-md border border-input bg-transparent px-[11px] py-2 text-base leading-[1.5] text-foreground shadow-xs transition-colors placeholder:text-muted-foreground focus:border-primary focus:outline-none focus:ring-[3px] focus:ring-ring" />
            </div>

            {/* Footer */}
            <div className="flex items-center justify-end gap-2 border-t border-border px-[22px] py-3">
              <Btn variant="outline" size="sm" onClick={onClose}>Hủy</Btn>
              <Btn variant="primary" size="sm" icon="settings" onClick={() => setOk(true)}>Đặt lại mật khẩu</Btn>
            </div>
          </>
          :
          /* Success */
          <>
            <div className="px-6 pb-[18px] pt-7 text-center">
              <div className="mx-auto mb-3.5 grid size-[52px] place-items-center rounded-full bg-success-soft">
                <Icon name="check-circle" size={26} className="text-success" />
              </div>
              <div className="text-md font-bold">Đã đặt lại mật khẩu</div>
              <div className="mx-auto mt-1.5 max-w-[380px] text-sm leading-[1.55] text-muted-foreground">
                Mật khẩu mới đã được gửi tới <strong className="text-foreground">{name}</strong> qua email. Vì lý do bảo mật, mật khẩu không hiển thị tại đây và không ai khác có thể xem.
              </div>
            </div>
            <div className="px-6 pb-2">
              {[
                { icon: 'mail', t: 'Mật khẩu mới đã được gửi qua email' },
                { icon: 'log-out', t: `${sessions} phiên đăng nhập đã được kết thúc` },
                { icon: 'settings', t: 'Buộc đổi mật khẩu lần đầu: Đã bật' },
                { icon: 'file-text', t: 'Đã ghi nhật ký kiểm toán (PASSWORD_RESET)' }
              ].map((r, i) =>
                <div key={i} className="flex items-center gap-[9px] px-0.5 py-1.5 text-xs text-foreground">
                  <Icon name={r.icon} size={13} className="shrink-0 text-success" />
                  <span>{r.t}</span>
                </div>
              )}
            </div>
            <div className="flex justify-end border-t border-border px-[22px] py-3">
              <Btn variant="primary" size="sm" icon="check" onClick={onClose}>Xong</Btn>
            </div>
          </>}
      </div>
    </div>
  );
};

// Wrapper cho canvas — mount dialog gán vai trò với dữ liệu demo (user chỉ có Employee)
const UMAssignRoleDialogDemo = () => (
  <div className="relative h-screen w-full bg-muted">
    <UMAssignRoleDialog name="Lê Thị Phương" currentRoles={[{ key: 'employee', primary: true }]} onClose={() => {}} />
  </div>
);

Object.assign(window, {
  UM_ROLE_CATALOG, UM_USER_ROLES, roleMeta, CURRENT_ACTOR_LEVEL,
  RoleCell, UMRoleRow, UMRoleManager, UMAssignRoleDialog, UMAssignRoleDialogDemo, UMResetPasswordDialog
});
