// ELS HRM — Module 02: RBAC data model (FLAT)
// Mô hình: KHÔNG kế thừa quyền theo level (flat) · level HIỆN trên UI, dùng làm TRẦN khi gán role ·
// phạm vi dữ liệu = quyền tường minh data:<domain>:<scope> ·
// custom role có SÀN quyền EMPLOYEE (khóa) + guardrail.
//
// ⚠️ Danh mục dưới đây là MẪU MINH HOẠ cho bản thiết kế — có thể đếm ÍT hơn hệ thống thật.
// NGUỒN CHUẨN của mọi mã screen:* / data:* / action:* là enum `Permission` trong `@hrm/core`
// (backend còn có screen:config; các data domain audit/custom_field/job_title/location/pay_grade;
// và nhiều action khác). Tài khoản người dùng KHÔNG phải data domain — kiểm soát qua
// screen:users + action:user:manage, KHÔNG có data:users:* (nên không có ScopeBadge cho users).

// ─── Catalog: Screen permissions ────────────────────────────────────────────────
const SCREEN_PERMS = [
  { code:'screen:dashboard',     label:'Bảng điều khiển',   desc:'Trang tổng quan cá nhân' },
  { code:'screen:employees',     label:'Nhân viên',          desc:'Danh sách & hồ sơ nhân viên' },
  { code:'screen:leave',         label:'Nghỉ phép',          desc:'Quản lý đơn nghỉ phép' },
  { code:'screen:attendance',    label:'Chấm công',          desc:'Bảng chấm công' },
  { code:'screen:timesheet',     label:'Bảng công',          desc:'Bảng công & timesheet' },
  { code:'screen:organizations', label:'Cơ cấu tổ chức',    desc:'Sơ đồ phòng ban' },
  { code:'screen:recruitment',   label:'Tuyển dụng',         desc:'Tin tuyển dụng & ứng viên' },
  { code:'screen:reports',       label:'Báo cáo',            desc:'Báo cáo & thống kê' },
  { code:'screen:users',         label:'Người dùng',         desc:'Quản lý tài khoản' },
  { code:'screen:roles',         label:'Phân quyền (RBAC)',  desc:'Màn hình vai trò & quyền', admin:true },
  { code:'screen:settings',      label:'Cấu hình hệ thống', desc:'Thiết lập toàn hệ thống',  admin:true },
];

// ─── Catalog: Data domains (own / dept / all) ───────────────────────────────────
const DATA_DOMAINS = [
  { domain:'employees',     label:'Hồ sơ nhân viên'    },
  { domain:'leave',         label:'Nghỉ phép'           },
  { domain:'attendance',    label:'Chấm công'           },
  { domain:'timesheet',     label:'Bảng công'           },
  { domain:'organizations', label:'Cơ cấu tổ chức'     },
  { domain:'recruitment',   label:'Tuyển dụng'          },
  { domain:'reports',       label:'Báo cáo'             },
];

// ─── Catalog: Action permissions ────────────────────────────────────────────────
// manage = gộp create/update/delete (CRUD) của 1 domain (employee, user, organization, role, recruitment...).
// Các mã còn lại là "capability" độc lập — cấp riêng, KHÔNG gộp vào manage (terminate, view_pii, approve...).
const ACTION_PERMS = [
  { code:'action:leave:create',       label:'Gửi yêu cầu nghỉ phép' },
  { code:'action:leave:approve',      label:'Phê duyệt nghỉ phép' },
  { code:'action:timesheet:submit',   label:'Nộp bảng công' },
  { code:'action:timesheet:approve',  label:'Phê duyệt bảng công' },
  { code:'action:attendance:adjust',  label:'Điều chỉnh chấm công' },
  { code:'action:employee:manage',    label:'Quản trị nhân viên (tạo/sửa/xoá)' },
  { code:'action:employee:terminate', label:'Chấm dứt lao động' },
  { code:'action:employee:view_pii',  label:'Xem PII đầy đủ (CCCD/MST)', sensitive:true },
  { code:'action:employee:view_salary', label:'Xem lương', sensitive:true },
  { code:'action:employee:edit_salary', label:'Sửa lương', sensitive:true },
  { code:'action:recruitment:manage', label:'Quản lý tin & ứng viên' },
  { code:'action:recruitment:approve', label:'Phê duyệt tuyển dụng' },
  { code:'action:report:export',      label:'Xuất báo cáo' },
  { code:'action:user:manage',        label:'Quản trị tài khoản (tạo/sửa/xoá · reset · mở khoá · gán vai trò)', sensitive:true },
  { code:'action:organization:manage', label:'Quản trị cơ cấu tổ chức (tạo/sửa/xoá)' },
  { code:'action:role:manage',        label:'Quản trị vai trò (tạo/sửa/xoá)', admin:true },
];

// ─── Catalog: Module nghiệp vụ (gom screen + data + action theo domain) ──────────
// Dùng cho khối chọn quyền master-detail: chọn module → hiện quyền của module đó.
const PERM_MODULES = [
  { key:'employees', label:'Nhân viên', icon:'users',
    screens:['screen:employees'], dataDomain:'employees',
    actions:['action:employee:manage','action:employee:terminate',
             'action:employee:view_pii','action:employee:view_salary','action:employee:edit_salary'] },
  { key:'leave', label:'Nghỉ phép', icon:'umbrella',
    screens:['screen:leave'], dataDomain:'leave',
    actions:['action:leave:create','action:leave:approve'] },
  { key:'attendance', label:'Chấm công', icon:'clock',
    screens:['screen:attendance'], dataDomain:'attendance',
    actions:['action:attendance:adjust'] },
  { key:'timesheet', label:'Bảng công', icon:'calendar-days',
    screens:['screen:timesheet'], dataDomain:'timesheet',
    actions:['action:timesheet:submit','action:timesheet:approve'] },
  { key:'recruitment', label:'Tuyển dụng', icon:'user-check',
    screens:['screen:recruitment'], dataDomain:'recruitment',
    actions:['action:recruitment:manage','action:recruitment:approve'] },
  { key:'organizations', label:'Cơ cấu tổ chức', icon:'building',
    screens:['screen:organizations'], dataDomain:'organizations',
    actions:['action:organization:manage'] },
  { key:'reports', label:'Báo cáo', icon:'file-text',
    screens:['screen:reports'], dataDomain:'reports',
    actions:['action:report:export'] },
  { key:'users', label:'Người dùng', icon:'user',
    screens:['screen:users'],
    actions:['action:user:manage'] },
  { key:'dashboard', label:'Cá nhân', icon:'layout-dashboard',
    screens:['screen:dashboard'], actions:[] },
  { key:'system', label:'Hệ thống', icon:'shield', locked:true,
    screens:['screen:roles','screen:settings'], actions:['action:role:manage'] },
];
function moduleTotals(m) {
  return m.screens.length + (m.dataDomain ? 1 : 0) + m.actions.length;
}
// Đếm số quyền ĐÃ CẤP trong 1 module — granted: Set mã quyền; scopes: {domain -> scope}
function moduleGrantedCount(m, granted, scopes) {
  let g = 0;
  for (const s of m.screens) if (granted.has(s)) g++;
  if (m.dataDomain && scopes && (scopes[m.dataDomain] || 'none') !== 'none') g++;
  for (const a of m.actions) if (granted.has(a)) g++;
  return { granted: g, total: moduleTotals(m) };
}

// ─── Guardrail: cấm cấp cho custom role ─────────────────────────────────────────
const GUARDRAIL_CODES = ['*', 'screen:roles', 'screen:settings', 'action:role:manage'];
const isGuardrailed = (code) => GUARDRAIL_CODES.includes(code);

// ─── SÀN quyền EMPLOYEE (baseline self-service) ─────────────────────────────────
const EMPLOYEE_BASELINE = [
  'screen:dashboard', 'screen:leave', 'screen:attendance', 'screen:timesheet',
  'data:employees:own', 'data:leave:own', 'data:attendance:own', 'data:timesheet:own',
  'action:leave:create', 'action:timesheet:submit',
];
const isBaseline = (code) => EMPLOYEE_BASELINE.includes(code);

// ─── Manage permission helper: action:<domain>:manage(_<x>)? — gộp CRUD ─────────
function isManagePermission(code){ return /^action:[a-z_]+:manage(_[a-z_]+)?$/.test(code); }

// ─── Scope helpers ──────────────────────────────────────────────────────────────
const SCOPE_RANK = { none:0, own:1, dept:2, all:3 };
const SCOPE_META = {
  none: { key:'none', label:'Không',     short:'—',          color:'var(--color-border-strong)',   bg:'transparent',          icon:'x' },
  own:  { key:'own',  label:'Của mình',  short:'Bản thân',   color:'oklch(0.55 0.16 300)',   bg:'oklch(0.96 0.03 300)', icon:'user',     dbg:'oklch(0.3 0.07 300)', dfg:'oklch(0.8 0.12 300)' },
  dept: { key:'dept', label:'Phòng ban', short:'Phòng ban',  color:'var(--color-info)',            bg:'var(--color-info-soft)',     icon:'building' },
  all:  { key:'all',  label:'Toàn bộ',   short:'Toàn bộ',    color:'var(--color-success)',         bg:'var(--color-success-soft)',  icon:'check-circle' },
};

// ─── Role definitions (perms = tập quyền TƯỜNG MINH, không kế thừa) ──────────────
// data:<domain>:<scope> được lưu như chuỗi đầy đủ trong perms.
function dataScopeSet(scopes) { // {employees:'all', leave:'dept', ...} -> codes
  return Object.entries(scopes).filter(([,s]) => s && s!=='none').map(([d,s]) => `data:${d}:${s}`);
}

const RBAC_ROLES = [
  {
    id:'r1', code:'ADMIN', displayName:'Quản trị viên',
    isSystem:true, full:true, level:100, users:1,
    color:'var(--color-destructive)', bg:'var(--color-destructive-soft)', icon:'settings',
    desc:'Toàn quyền hệ thống. Quản lý cấu hình, vai trò, người dùng và nhật ký kiểm toán.',
    // Liệt kê ĐỦ mã tường minh (mọi screen + mọi data:*:all + mọi action) — mirror seed
    // backend, KHÔNG dùng '*'. full:true chỉ là lối tắt render "Toàn bộ" trong bảng/ma trận.
    perms:[
      ...SCREEN_PERMS.map(p => p.code),
      ...dataScopeSet(Object.fromEntries(DATA_DOMAINS.map(d => [d.domain, 'all']))),
      ...ACTION_PERMS.map(p => p.code),
    ],
  },
  {
    id:'r2', code:'HR_MANAGER', displayName:'Quản lý Nhân sự',
    isSystem:false, level:70, users:3,
    color:'var(--color-primary)', bg:'var(--color-primary-soft)', icon:'users',
    desc:'Quản lý nhân sự xuyên phòng ban. Phê duyệt nghỉ phép, bảng công và quản lý tuyển dụng.',
    perms:[
      'screen:dashboard','screen:employees','screen:leave','screen:attendance','screen:timesheet',
      'screen:organizations','screen:recruitment','screen:reports','screen:users',
      ...dataScopeSet({ employees:'all', leave:'all', attendance:'all', timesheet:'all', organizations:'all', recruitment:'all', reports:'all' }),
      'action:leave:create','action:leave:approve','action:timesheet:submit','action:timesheet:approve',
      'action:attendance:adjust','action:employee:manage','action:employee:terminate',
      // edit_salary KHÔNG cấp HR mặc định (finding 19 — nhạy cảm nhất, least-privilege).
      'action:employee:view_pii','action:employee:view_salary',
      'action:recruitment:manage','action:report:export','action:user:manage',
    ],
  },
  {
    id:'r3', code:'DEPT_MANAGER', displayName:'Trưởng phòng',
    isSystem:false, level:50, users:8,
    color:'var(--color-info)', bg:'var(--color-info-soft)', icon:'briefcase',
    desc:'Quản lý nhân sự trong phòng ban. Phê duyệt yêu cầu của nhóm mình.',
    perms:[
      ...EMPLOYEE_BASELINE.filter(c => c.startsWith('screen') || c.startsWith('action')),
      'screen:employees','screen:organizations','screen:reports',
      ...dataScopeSet({ employees:'dept', leave:'dept', attendance:'dept', timesheet:'dept', organizations:'dept', reports:'dept' }),
      'data:employees:own','data:leave:own','data:attendance:own','data:timesheet:own',
      'action:leave:approve','action:timesheet:approve','action:report:export',
    ],
  },
  {
    id:'r4', code:'EMPLOYEE', displayName:'Nhân viên',
    isSystem:true, level:10, users:235,
    color:'var(--color-success)', bg:'var(--color-success-soft)', icon:'user',
    desc:'Truy cập dữ liệu cá nhân và các tính năng self-service cơ bản.',
    perms:[ ...EMPLOYEE_BASELINE ],
  },
  {
    id:'r6', code:'HR_VIEWER', displayName:'Nhân sự (Chỉ xem)',
    isSystem:false, level:60, users:2,
    color:'oklch(0.55 0.02 260)', bg:'var(--color-muted)', icon:'eye',
    desc:'Vai trò tùy chỉnh read-only. Xem toàn bộ hồ sơ nhân viên nhưng KHÔNG có action:employee:* (không sửa, không PII, không lương).',
    perms:[
      ...EMPLOYEE_BASELINE,
      'screen:employees','screen:reports',
      'data:employees:all','data:reports:all',
    ],
  },
  {
    id:'r5', code:'RECRUITER', displayName:'Chuyên viên Tuyển dụng',
    isSystem:false, level:40, users:2,
    color:'oklch(0.55 0.16 300)', bg:'oklch(0.96 0.03 300)', icon:'user-check',
    desc:'Vai trò tùy chỉnh. Phụ trách tuyển dụng — kế thừa sàn quyền Nhân viên, được cấp thêm quyền tuyển dụng.',
    perms:[
      ...EMPLOYEE_BASELINE,
      'screen:employees','screen:recruitment',
      'data:recruitment:all','data:employees:dept',
      'action:recruitment:manage',
    ],
  },
];

const RBAC_SYSTEM_ROLES = RBAC_ROLES.filter(r => r.isSystem);
const RBAC_CUSTOM_ROLES = RBAC_ROLES.filter(r => !r.isSystem);
const RBAC_TOTAL_USERS  = RBAC_ROLES.reduce((s,r) => s + r.users, 0);
const roleById = (id) => RBAC_ROLES.find(r => r.id === id);

// ─── Per-role query helpers (FLAT — không suy từ level) ──────────────────────────
function roleHas(role, code) {
  if (role.full) return true;
  return role.perms.includes(code);
}
// Phạm vi dữ liệu của 1 domain, suy TRỰC TIẾP từ data:* (lấy mức cao nhất)
function domainScope(role, domain) {
  if (role.full) return 'all';
  let best = 'none';
  for (const sc of ['own','dept','all']) {
    if (role.perms.includes(`data:${domain}:${sc}`) && SCOPE_RANK[sc] > SCOPE_RANK[best]) best = sc;
  }
  return best;
}
// Tóm tắt phạm vi dữ liệu toàn cục cho thẻ/sidebar
function dataScopeSummary(role) {
  if (role.full) return { key:'all', label:'Toàn bộ dữ liệu' };
  let best = 'none';
  for (const d of DATA_DOMAINS) {
    const s = domainScope(role, d.domain);
    if (SCOPE_RANK[s] > SCOPE_RANK[best]) best = s;
  }
  return { key:best, label: best==='all' ? 'Toàn bộ dữ liệu' : best==='dept' ? 'Theo phòng ban' : best==='own' ? 'Chỉ dữ liệu bản thân' : 'Không có quyền dữ liệu' };
}
function permCount(role) {
  if (role.full) return SCREEN_PERMS.length + DATA_DOMAINS.length + ACTION_PERMS.length;
  // số quyền hiệu lực = screens + domains có scope + actions
  const screens = SCREEN_PERMS.filter(p => roleHas(role, p.code)).length;
  const datas   = DATA_DOMAINS.filter(d => domainScope(role, d.domain) !== 'none').length;
  const actions = ACTION_PERMS.filter(p => roleHas(role, p.code)).length;
  return screens + datas + actions;
}

Object.assign(window, {
  SCREEN_PERMS, DATA_DOMAINS, ACTION_PERMS, GUARDRAIL_CODES, EMPLOYEE_BASELINE,
  SCOPE_RANK, SCOPE_META, RBAC_ROLES, RBAC_SYSTEM_ROLES, RBAC_CUSTOM_ROLES,
  RBAC_TOTAL_USERS, roleById, roleHas, domainScope, dataScopeSummary, permCount,
  isGuardrailed, isBaseline, isManagePermission,
  PERM_MODULES, moduleTotals, moduleGrantedCount,
});
