/**
 * Must match `roles.role_name` from the API after normalization (trim + lowercase).
 * DB example: EXECUTER/VARIFIER → executer/varifier
 */
export const NORMALIZED_ROLE_EXECUTER_VERIFIER = 'executer/varifier';

/**
 * `hse.roles.role_id` — same as Risk_assessment_backend / SAT_backend `ROLE_IDS`.
 * 1 Admin, 2 User, 3 Support, 4 EXECUTER/VARIFIER
 *
 * Risk Assessment: executor/verifier users must be **4** (not 3 Support).
 */
export const HSE_ROLE_IDS = Object.freeze({
  ADMIN: 1,
  USER: 2,
  SUPPORT: 3,
  EXECUTOR_VERIFIER: 4
});

/** Explicit id for EXECUTER/VARIFIER in Risk Assessment + `hse.roles` (always 4). */
export const RISK_EXECUTOR_VERIFIER_ROLE_ID = HSE_ROLE_IDS.EXECUTOR_VERIFIER;

/** Align with API `role` string (handles spaces around `/` and unicode slashes). */
export function normalizeRoleKey(role) {
  return String(role || '')
    .trim()
    .toLowerCase()
    .replace(/\u2215/g, '/')
    .replace(/\uff0f/g, '/')
    .replace(/\s*\/\s*/g, '/');
}

function decodeJwtPayload(token) {
  if (typeof token !== 'string' || !token.includes('.')) return null;
  try {
    const part = token.split('.')[1];
    if (!part) return null;
    return JSON.parse(atob(part));
  } catch {
    return null;
  }
}

/**
 * Map `hse.roles.role_id` to Risk Assessment UI role string.
 */
function hseRoleIdToRiskRole(roleId) {
  const id = Number(roleId);
  if (id === HSE_ROLE_IDS.ADMIN) return 'admin';
  if (id === HSE_ROLE_IDS.USER) return 'user';
  if (id === HSE_ROLE_IDS.SUPPORT) return 'user';
  if (id === RISK_EXECUTOR_VERIFIER_ROLE_ID) return NORMALIZED_ROLE_EXECUTER_VERIFIER;
  return '';
}

function priorityPickFromRoleIds(roleIds) {
  const ids = (roleIds || [])
    .map((id) => Number(id))
    .filter((n) => !Number.isNaN(n));
  if (ids.includes(HSE_ROLE_IDS.ADMIN)) return 'admin';
  if (ids.includes(RISK_EXECUTOR_VERIFIER_ROLE_ID)) {
    return NORMALIZED_ROLE_EXECUTER_VERIFIER;
  }
  if (ids.includes(HSE_ROLE_IDS.USER) || ids.includes(HSE_ROLE_IDS.SUPPORT)) {
    return 'user';
  }
  return 'user';
}

function priorityPickFromRoleNames(names) {
  const normalized = names.map((n) => normalizeRoleKey(n));
  if (normalized.some((n) => n === 'admin')) return 'admin';
  if (normalized.some((n) => isExecuterVerifierRole(n))) {
    return NORMALIZED_ROLE_EXECUTER_VERIFIER;
  }
  return 'user';
}

/**
 * Resolve UI role from JWT payload. SAT tokens use `userId` + `roles`/`roleIds`;
 * ORAC-native tokens use `user_id` + `role` / `role_id` and often `iss` from ORAC.
 */
function roleFromDecodedJwt(jwt) {
  if (!jwt || typeof jwt !== 'object') return '';

  const hasSatUserId = jwt.userId != null;
  const hasOracUserId = jwt.user_id != null;
  const iss = String(jwt.iss || '').toLowerCase();
  const oracIssuer = iss.includes('orac');

  const satLike =
    hasSatUserId &&
    !hasOracUserId &&
    (Array.isArray(jwt.roles) || Array.isArray(jwt.roleIds));

  if (satLike) {
    if (Array.isArray(jwt.roles) && jwt.roles.length > 0) {
      return priorityPickFromRoleNames(jwt.roles);
    }
    if (Array.isArray(jwt.roleIds) && jwt.roleIds.length > 0) {
      return priorityPickFromRoleIds(jwt.roleIds);
    }
    return 'user';
  }

  if (hasOracUserId || oracIssuer) {
    if (typeof jwt.role === 'string' && jwt.role.trim()) {
      return normalizeRoleKey(jwt.role);
    }
    if (jwt.role_id != null) {
      const r = hseRoleIdToRiskRole(jwt.role_id);
      if (r) return r;
    }
    return '';
  }

  if (Array.isArray(jwt.roles) && jwt.roles.length > 0) {
    return priorityPickFromRoleNames(jwt.roles);
  }
  if (Array.isArray(jwt.roleIds) && jwt.roleIds.length > 0) {
    return priorityPickFromRoleIds(jwt.roleIds);
  }
  if (typeof jwt.role === 'string' && jwt.role.trim()) {
    return normalizeRoleKey(jwt.role);
  }
  if (jwt.role_id != null) {
    const r = hseRoleIdToRiskRole(jwt.role_id);
    if (r) return r;
  }

  return '';
}

/** Stable role string for React state / localStorage (login body or restored session).
 *  Handles both the HSE (SAT) token shape { roles: ["Admin"], roleIds: [1] }
 *  and the stored-session shape { role: "admin", user: { role_name, role_id } }.
 */
export function sessionRoleFromLoginPayload(payload) {
  const token = payload?.token;
  const jwt = decodeJwtPayload(token);
  if (jwt) {
    const fromJwt = roleFromDecodedJwt(jwt);
    if (fromJwt) return fromJwt;
  }

  const topRole = payload?.role;
  if (topRole != null && topRole !== '') return normalizeRoleKey(topRole);

  const allRoles = payload?.user?.allRoles;
  if (Array.isArray(allRoles) && allRoles.length > 0) {
    const roleName = allRoles[0]?.roleName ?? allRoles[0]?.role_name ?? '';
    if (roleName) return normalizeRoleKey(roleName);
    const roleId = Number(allRoles[0]?.roleId ?? allRoles[0]?.role_id);
    const mapped = hseRoleIdToRiskRole(roleId);
    if (mapped) return mapped;
  }

  const legacyRoleName = payload?.user?.role_name ?? '';
  if (legacyRoleName) return normalizeRoleKey(legacyRoleName);

  const id = Number(payload?.user?.role_id);
  if (id === HSE_ROLE_IDS.ADMIN) return 'admin';
  if (id === HSE_ROLE_IDS.USER) return 'user';
  if (id === HSE_ROLE_IDS.SUPPORT) return 'user';
  if (id === RISK_EXECUTOR_VERIFIER_ROLE_ID) return NORMALIZED_ROLE_EXECUTER_VERIFIER;

  return '';
}

export function isExecuterVerifierRole(role) {
  const n = normalizeRoleKey(role);
  return (
    n === NORMALIZED_ROLE_EXECUTER_VERIFIER ||
    n === 'executor' ||
    n === 'executer/verifier'
  );
}
