import { test } from 'node:test';
import assert from 'node:assert/strict';
import IamCapabilitiesService from '@/services/iam_capabilities';
import { ROLE_NAMES, ROLE_SCOPES } from '@/shared/constants/roles';
import type { CurrentUser } from '@/db/api/types';

function permission(name: string) {
  return { name };
}

function user(
  role: string,
  scope: string,
  permissionNames: readonly string[],
  globalAccess = false,
): CurrentUser {
  return {
    id: `${role}-user`,
    app_role: {
      name: role,
      scope,
      globalAccess,
      permissions: permissionNames.map(permission),
    },
  };
}

const allTenantCreatePermissions = [
  'CREATE_ORGANIZATIONS',
  'CREATE_SCHOOLS',
  'CREATE_CAMPUSES',
  'CREATE_CLASSES',
  'CREATE_USERS',
] as const;

test('super_admin creates organizations through owner setup and can create child location types', () => {
  const caps = IamCapabilitiesService.current(
    user(ROLE_NAMES.SUPER_ADMIN, ROLE_SCOPES.SYSTEM, [], true),
  );
  assert.deepEqual(caps.creatableTenantTypes, ['school', 'campus', 'class']);
  assert.equal(caps.manageableRoleNames.includes(ROLE_NAMES.SUPER_ADMIN), false);
  assert.equal(caps.manageableRoleNames.includes(ROLE_NAMES.SYSTEM_ADMIN), true);
  assert.equal(caps.canCreateOwnerWithOrganization, true);
});

test('system_admin cannot manage platform admin roles', () => {
  const caps = IamCapabilitiesService.current(
    user(ROLE_NAMES.SYSTEM_ADMIN, ROLE_SCOPES.SYSTEM, allTenantCreatePermissions, true),
  );
  assert.equal(caps.manageableRoleNames.includes(ROLE_NAMES.SUPER_ADMIN), false);
  assert.equal(caps.manageableRoleNames.includes(ROLE_NAMES.SYSTEM_ADMIN), false);
  assert.equal(caps.manageableRoleNames.includes(ROLE_NAMES.OWNER), true);
});

test('owner and superintendent create school/campus/class but not organization directly', () => {
  for (const role of [ROLE_NAMES.OWNER, ROLE_NAMES.SUPERINTENDENT]) {
    const caps = IamCapabilitiesService.current(
      user(role, ROLE_SCOPES.ORGANIZATION, allTenantCreatePermissions),
    );
    assert.deepEqual(caps.creatableTenantTypes, ['school', 'campus', 'class']);
  }
});

test('principal creates campus/class, director creates class only', () => {
  const principal = IamCapabilitiesService.current(
    user(ROLE_NAMES.PRINCIPAL, ROLE_SCOPES.SCHOOL, allTenantCreatePermissions),
  );
  assert.deepEqual(principal.creatableTenantTypes, ['campus', 'class']);

  const director = IamCapabilitiesService.current(
    user(ROLE_NAMES.DIRECTOR, ROLE_SCOPES.CAMPUS, allTenantCreatePermissions),
  );
  assert.deepEqual(director.creatableTenantTypes, ['class']);
});

test('read-only and external roles cannot create tenants or manage users', () => {
  for (const role of [
    ROLE_NAMES.REGISTRAR,
    ROLE_NAMES.OFFICE_MANAGER,
    ROLE_NAMES.TEACHER,
    ROLE_NAMES.SUPPORT_STAFF,
    ROLE_NAMES.STUDENT,
    ROLE_NAMES.GUARDIAN,
    ROLE_NAMES.GUEST,
  ]) {
    const caps = IamCapabilitiesService.current(
      user(role, ROLE_SCOPES.CAMPUS, ['READ_USERS']),
    );
    assert.deepEqual(caps.creatableTenantTypes, []);
    assert.deepEqual(caps.manageableRoleNames, []);
  }
});
