export const ROLE_CATALOG = [
  {
    name: "super_admin",
    label: "Administrateur",
    visible: true,
    permissions: ["*"],
  },
  {
    name: "chief_accountant",
    label: "Chef comptable",
    visible: true,
    permissions: [
      "dashboard:read",
      "accounts:read",
      "accounts:create",
      "accounts:update",
      "accounts:delete",
      "journals:read",
      "journals:create",
      "journals:update",
      "journals:delete",
      "fiscal_years:read",
      "fiscal_years:create",
      "periods:read",
      "periods:close",
      "entries:read",
      "entries:create",
      "entries:update",
      "entries:delete",
      "entries:validate",
      "entries:export",
      "matching:read",
      "matching:create",
      "matching:update",
      "matching:export",
      "matching_admin",
      "reconciliation:read",
      "reconciliation:create",
      "reconciliation:update",
      "reconciliation:validate",
      "reconciliation:export",
      "closure:read",
      "closure:create",
      "closure:validate",
      "closure:reopen",
      "assets:read",
      "assets:create",
      "assets:update",
      "assets:delete",
      "assets:validate",
      "assets:export",
      "reports:read",
      "reports:export",
      "financial_statements:read",
      "financial_statements:export",
      "audit:read",
      "login_history:read",
    ],
  },
  {
    name: "accountant",
    label: "Comptable",
    visible: true,
    permissions: [
      "dashboard:read",
      "accounts:read",
      "journals:read",
      "entries:read",
      "entries:create",
      "entries:update",
      "entries:export",
      "matching:read",
      "reports:read",
      "reports:export",
    ],
  },
  {
    name: "management_controller",
    label: "Contrôle de gestion",
    visible: true,
    permissions: [
      "dashboard:read",
      "reports:read",
      "reports:export",
      "financial_statements:read",
      "audit:read",
    ],
  },
  {
    name: "cashier",
    label: "Caissier",
    visible: true,
    permissions: [
      "dashboard:read",
      "treasury:cash:read",
      "treasury:cash:create",
      "treasury:cash:update",
      "reports:read",
      "reports:export",
    ],
  },
  {
    name: "treasurer",
    label: "Trésorier",
    visible: true,
    permissions: [
      "dashboard:read",
      "treasury:cash:read",
      "treasury:cash:create",
      "treasury:cash:update",
      "treasury:bank:read",
      "treasury:bank:create",
      "treasury:bank:update",
      "reconciliation:read",
      "reconciliation:create",
      "reconciliation:update",
      "reconciliation:validate",
      "reconciliation:export",
      "reports:read",
      "reports:export",
    ],
  },
  {
    name: "executive",
    label: "Direction",
    visible: true,
    permissions: [
      "dashboard:read",
      "reports:read",
      "reports:export",
      "financial_statements:read",
      "financial_statements:export",
    ],
  },
  {
    name: "mgx_manager",
    label: "Responsable MGX",
    visible: true,
    permissions: [
      "mgx:vehicles:read",
      "mgx:vehicles:create",
      "mgx:vehicles:update",
      "mgx:vehicles:delete",
      "mgx:vehicles:export",
      "mgx:it_assets:read",
      "mgx:it_assets:create",
      "mgx:it_assets:update",
      "mgx:it_assets:delete",
      "mgx:it_assets:export",
      "mgx:fuel:read",
      "mgx:fuel:create",
      "mgx:fuel:update",
      "mgx:fuel:delete",
      "mgx:fuel:export",
      "mgx:maintenance:read",
      "mgx:maintenance:create",
      "mgx:maintenance:update",
      "mgx:maintenance:delete",
      "mgx:maintenance:validate",
      "mgx:maintenance:export",
      "mgx:purchases:read",
      "mgx:purchases:create",
      "mgx:purchases:update",
      "mgx:purchases:delete",
      "mgx:purchases:validate",
      "mgx:purchases:export",
      "mgx:services:read",
      "mgx:services:create",
      "mgx:services:update",
      "mgx:services:delete",
      "mgx:services:export",
      "mgx:rentals:read",
      "mgx:rentals:create",
      "mgx:rentals:update",
      "mgx:rentals:delete",
      "mgx:rentals:export",
      "mgx:consumables:read",
      "mgx:consumables:create",
      "mgx:consumables:update",
      "mgx:consumables:delete",
      "mgx:consumables:export",
      "mgx:suppliers:read",
      "mgx:suppliers:create",
      "mgx:suppliers:update",
      "mgx:suppliers:delete",
      "mgx:suppliers:export",
      "mgx:treasury:read",
      "mgx:treasury:create",
      "mgx:treasury:update",
      "mgx:treasury:delete",
      "mgx:treasury:validate",
      "mgx:treasury:export",
      "mgx:alerts:read",
      "mgx:alerts:update",
      "mgx:alerts:delete",
      "mgx:alerts:validate",
      "mgx:alerts:export",
      "mgx:reports:read",
      "mgx:reports:export",
      "mgx:admin:read",
      "mgx:admin:create",
      "mgx:admin:update",
      "mgx:admin:delete",
      "mgx:admin:export",
    ],
  },
  {
    name: "mgx_agent",
    label: "Agent MGX",
    visible: true,
    permissions: [
      "mgx:vehicles:read",
      "mgx:maintenance:read",
      "mgx:maintenance:create",
      "mgx:purchases:read",
      "mgx:purchases:create",
      "mgx:consumables:read",
      "mgx:services:read",
      "mgx:rentals:read",
    ],
  },
  {
    name: "mgx_chauffeur",
    label: "Chauffeur",
    visible: true,
    permissions: [
      "mgx:vehicles:read",
      "mgx:maintenance:read",
      "mgx:maintenance:create",
      "mgx:purchases:read",
      "mgx:purchases:create",
      "mgx:consumables:read",
      "mgx:services:read",
      "mgx:rentals:read",
    ],
  },
  {
    name: "mgx_chef_parc",
    label: "Chef de parc",
    visible: true,
    permissions: [
      "mgx:vehicles:read",
      "mgx:vehicles:update",
      "mgx:vehicles:export",
      "mgx:maintenance:read",
      "mgx:maintenance:create",
      "mgx:maintenance:update",
      "mgx:maintenance:validate",
      "mgx:maintenance:export",
      "mgx:purchases:read",
      "mgx:purchases:create",
      "mgx:purchases:update",
      "mgx:purchases:export",
      "mgx:consumables:read",
      "mgx:services:read",
      "mgx:rentals:read",
      "mgx:alerts:read",
      "mgx:alerts:update",
      "mgx:alerts:validate",
      "mgx:reports:read",
    ],
  },
  {
    name: "mgx_mecanicien",
    label: "Mécanicien",
    visible: true,
    permissions: [
      "mgx:vehicles:read",
      "mgx:maintenance:read",
      "mgx:maintenance:update",
      "mgx:consumables:read",
      "mgx:consumables:create",
    ],
  },
  {
    name: "mgx_back_office",
    label: "Back Office MGX",
    visible: true,
    permissions: [
      "mgx:purchases:read",
      "mgx:purchases:update",
      "mgx:purchases:validate",
      "mgx:purchases:export",
      "mgx:suppliers:read",
      "mgx:treasury:read",
      "mgx:treasury:validate",
      "mgx:reports:read",
    ],
  },
  {
    name: "mgx_controleur",
    label: "Contrôleur MGX",
    visible: true,
    permissions: [
      "mgx:vehicles:read",
      "mgx:fuel:read",
      "mgx:fuel:create",
      "mgx:suppliers:read",
    ],
  },
  {
    name: "manager",
    label: "Manager (legacy)",
    visible: false,
    permissions: [
      "dashboard:read",
      "reports:read",
      "entries:validate",
      "financial_statements:read",
      "matching_admin",
      "audit:read",
      "users:read",
      "users:create",
      "users:update",
      "users:delete",
      "roles:read",
      "roles:create",
      "roles:update",
      "system_settings:read",
      "system_settings:update",
      "backup:export",
      "closure:reopen",
    ],
  },
  {
    name: "auditor",
    label: "Auditeur (legacy)",
    visible: false,
    permissions: [
      "audit:read",
      "login_history:read",
      "reports:read",
      "financial_statements:read",
    ],
  },
];

export const ROLE_LABELS = ROLE_CATALOG.reduce((accumulator, role) => {
  accumulator[role.name] = role.label;
  return accumulator;
}, {});

export const ADMIN_ROLES = new Set(["super_admin", "manager"]);
export const ADMIN_ROOM_ROLES = new Set(["super_admin", "manager"]);
export const REOPEN_ROLES = new Set(["super_admin", "manager", "chief_accountant"]);

const mgxPermissionRow = (key, label, resource, options = {}) => ({
  key,
  label,
  permissions: {
    read: [`mgx:${resource}:read`],
    create: options.create === false ? [] : [`mgx:${resource}:create`],
    update: options.update === false ? [] : [`mgx:${resource}:update`],
    delete: options.delete === false ? [] : [`mgx:${resource}:delete`],
    validate: options.validate ? [`mgx:${resource}:validate`] : [],
    export: options.export === false ? [] : [`mgx:${resource}:export`],
  },
});

export const PERMISSION_GRID = [
  {
    key: "entries",
    label: "Saisie",
    permissions: {
      read: ["entries:read"],
      create: ["entries:create"],
      update: ["entries:update"],
      delete: ["entries:delete"],
      validate: ["entries:validate"],
      export: ["entries:export"],
    },
  },
  {
    key: "validation",
    label: "Validation",
    permissions: {
      read: ["entries:read"],
      create: [],
      update: [],
      delete: [],
      validate: ["entries:validate"],
      export: ["entries:export"],
    },
  },
  {
    key: "matching",
    label: "Lettrage",
    permissions: {
      read: ["matching:read"],
      create: ["matching:create"],
      update: ["matching:update"],
      delete: ["matching_admin"],
      validate: ["matching_admin"],
      export: ["matching:export"],
    },
  },
  {
    key: "reconciliation",
    label: "Rapprochement",
    permissions: {
      read: ["reconciliation:read"],
      create: ["reconciliation:create"],
      update: ["reconciliation:update"],
      delete: [],
      validate: ["reconciliation:validate"],
      export: ["reconciliation:export"],
    },
  },
  {
    key: "closure",
    label: "Clôture",
    permissions: {
      read: ["closure:read"],
      create: ["closure:create"],
      update: [],
      delete: [],
      validate: ["closure:validate"],
      export: [],
    },
  },
  {
    key: "assets",
    label: "Immobilisations",
    permissions: {
      read: ["assets:read"],
      create: ["assets:create"],
      update: ["assets:update"],
      delete: ["assets:delete"],
      validate: ["assets:validate"],
      export: ["assets:export"],
    },
  },
  {
    key: "reports",
    label: "États",
    permissions: {
      read: ["reports:read", "financial_statements:read"],
      create: [],
      update: [],
      delete: [],
      validate: [],
      export: ["reports:export", "financial_statements:export"],
    },
  },
  mgxPermissionRow("mgx_vehicles", "MGX · Parc auto", "vehicles"),
  mgxPermissionRow("mgx_it_assets", "MGX · Parc informatique", "it_assets"),
  mgxPermissionRow("mgx_fuel", "MGX · Carburant", "fuel"),
  mgxPermissionRow("mgx_maintenance", "MGX · Maintenance", "maintenance", { validate: true }),
  mgxPermissionRow("mgx_purchases", "MGX · Achats", "purchases", { validate: true }),
  mgxPermissionRow("mgx_services", "MGX · Prestations", "services"),
  mgxPermissionRow("mgx_rentals", "MGX · Locations", "rentals"),
  mgxPermissionRow("mgx_consumables", "MGX · Consommables", "consumables"),
  mgxPermissionRow("mgx_suppliers", "MGX · Fournisseurs", "suppliers"),
  mgxPermissionRow("mgx_treasury", "MGX · Trésorerie", "treasury", { validate: true }),
  mgxPermissionRow("mgx_alerts", "MGX · Alertes", "alerts", { create: false, validate: true }),
  mgxPermissionRow("mgx_reports", "MGX · Reporting", "reports", { create: false, update: false, delete: false }),
  mgxPermissionRow("mgx_admin", "MGX · Administration", "admin"),
  {
    key: "admin",
    label: "Admin",
    permissions: {
      read: ["users:read", "roles:read", "audit:read", "login_history:read", "system_settings:read"],
      create: ["users:create", "roles:create"],
      update: ["users:update", "roles:update", "system_settings:update"],
      delete: ["users:delete"],
      validate: [],
      export: ["backup:export"],
    },
  },
  {
    key: "reopen",
    label: "Réouverture",
    permissions: {
      read: ["closure:read"],
      create: [],
      update: [],
      delete: [],
      validate: ["closure:reopen"],
      export: [],
    },
  },
];

export const getRoleMeta = (roleName) =>
  ROLE_CATALOG.find((role) => role.name === roleName) || null;

export const getVisibleRoles = () => ROLE_CATALOG.filter((role) => role.visible);

export const getDefaultPermissionsForRole = (roleName) =>
  getRoleMeta(roleName)?.permissions || [];

export const normalizePermissions = (permissions) =>
  Array.isArray(permissions) ? permissions.map((permission) => String(permission)) : [];

export const fetchRolePermissions = async (db, roleName) => {
  const { rows } = await db.query(
    `
      SELECT permissions
      FROM roles
      WHERE name = $1
      LIMIT 1
    `,
    [roleName],
  );

  return normalizePermissions(rows[0]?.permissions || getDefaultPermissionsForRole(roleName));
};

export const hasPermission = (permissions, ...requiredPermissions) => {
  const normalized = normalizePermissions(permissions);

  if (normalized.includes("*")) {
    return true;
  }

  return requiredPermissions.some((permission) => normalized.includes(permission));
};

export const canManageAdmin = (role, permissions) =>
  ADMIN_ROLES.has(role) ||
  hasPermission(
    permissions,
    "users:create",
    "users:update",
    "roles:update",
    "system_settings:update",
  );

export const canReadAudit = (role, permissions) =>
  ADMIN_ROLES.has(role) || hasPermission(permissions, "audit:read");

export const canReadLoginHistory = (role, permissions) =>
  ADMIN_ROLES.has(role) || hasPermission(permissions, "login_history:read");

export const canExportBackup = (role, permissions) =>
  ADMIN_ROLES.has(role) || hasPermission(permissions, "backup:export");

export const buildPermissionGridState = (permissions) =>
  PERMISSION_GRID.map((module) => ({
    key: module.key,
    label: module.label,
    cells: Object.entries(module.permissions).reduce((accumulator, [action, required]) => {
      accumulator[action] = required.length
        ? hasPermission(permissions, ...required)
        : false;
      return accumulator;
    }, {}),
  }));

export const syncDefaultRoles = async (db) => {
  for (const role of ROLE_CATALOG) {
    await db.query(
      `
        INSERT INTO roles (name, permissions)
        VALUES ($1, $2::jsonb)
        ON CONFLICT (name)
        DO UPDATE SET permissions = EXCLUDED.permissions
      `,
      [role.name, JSON.stringify(role.permissions)],
    );
  }
};
