export function normalizeAllowedModules(runtime: any): string[] | null {
  const directModules = [
    ...(toArray(runtime?.enabled_modules)),
    ...(toArray(runtime?.enabledModules)),
    ...(toArray(runtime?.modules)),
    ...(toArray(runtime?.config_json?.modules)),
    ...(toArray(runtime?.configJson?.modules)),
  ];

  const permissionCandidates = [
    ...(toArray(runtime?.permission_keys)),
    ...(toArray(runtime?.permissionKeys)),
    ...permissionObjectKeys(runtime?.permissions),
    ...permissionObjectKeys(runtime?.config_json?.permissions),
    ...permissionObjectKeys(runtime?.configJson?.permissions),
  ];

  const derivedModules = permissionCandidates
    .map((value) => parsePermissionToModule(String(value || '')))
    .filter(Boolean) as string[];

  const all = [...directModules, ...derivedModules]
    .map((value) => String(value || '').trim().toUpperCase())
    .filter(Boolean);

  if (!all.length) return null;
  return Array.from(new Set(all));
}

function toArray(value: unknown): string[] {
  if (!Array.isArray(value)) return [];
  return value.map((item) => String(item || ''));
}

function permissionObjectKeys(value: unknown): string[] {
  if (!value || typeof value !== 'object' || Array.isArray(value)) return [];
  return Object.keys(value as Record<string, unknown>);
}

function parsePermissionToModule(permission: string): string | null {
  const normalized = permission.trim().toUpperCase();
  if (!normalized) return null;

  // Example: DEPARTMENTS_VIEW
  const suffixMatch = normalized.match(/^([A-Z0-9_]+)_(VIEW|CREATE|UPDATE|DELETE)$/);
  if (suffixMatch) return suffixMatch[1];

  // Example: DEPARTMENT_MANAGEMENT:VIEW
  if (normalized.includes(':')) return normalized.split(':')[0] || null;

  // Example: departments.view
  if (normalized.includes('.')) return normalized.split('.')[0] || null;

  // Already a module key
  return normalized;
}
