import { ROLE_NAMES, ROLE_SCOPES, type RoleName } from '@/shared/constants/roles';
import { hasFeaturePermission, getRoleScope } from '@/services/shared/access';
import { manageableRoleNamesFor } from '@/services/shared/role-policy';
import type { CurrentUser } from '@/db/api/types';

export type CreatableTenantType = 'school' | 'campus' | 'class';

export interface IamCapabilities {
  readonly manageableRoleNames: readonly RoleName[];
  readonly creatableTenantTypes: readonly CreatableTenantType[];
  readonly canCreateOwnerWithOrganization: boolean;
  readonly canEditOwnProfile: boolean;
  readonly canEditOwnOrganization: boolean;
  readonly canAssignPrincipal: boolean;
  readonly canAssignDirector: boolean;
}

function tenantTypesFor(currentUser?: CurrentUser): CreatableTenantType[] {
  const scope = getRoleScope(currentUser);
  const types: CreatableTenantType[] = [];

  if (
    hasFeaturePermission(currentUser, 'CREATE_SCHOOLS')
    && (
      scope === ROLE_SCOPES.SYSTEM
      || scope === ROLE_SCOPES.ORGANIZATION
    )
  ) {
    types.push('school');
  }
  if (
    hasFeaturePermission(currentUser, 'CREATE_CAMPUSES')
    && (
      scope === ROLE_SCOPES.SYSTEM
      || scope === ROLE_SCOPES.ORGANIZATION
      || scope === ROLE_SCOPES.SCHOOL
    )
  ) {
    types.push('campus');
  }
  if (
    hasFeaturePermission(currentUser, 'CREATE_CLASSES')
    && (
      scope === ROLE_SCOPES.SYSTEM
      || scope === ROLE_SCOPES.ORGANIZATION
      || scope === ROLE_SCOPES.SCHOOL
      || scope === ROLE_SCOPES.CAMPUS
    )
  ) {
    types.push('class');
  }

  return types;
}

class IamCapabilitiesService {
  static current(currentUser?: CurrentUser): IamCapabilities {
    const manageableRoleNames = manageableRoleNamesFor(currentUser);
    return {
      manageableRoleNames,
      creatableTenantTypes: tenantTypesFor(currentUser),
      canCreateOwnerWithOrganization:
        manageableRoleNames.includes(ROLE_NAMES.OWNER)
        && hasFeaturePermission(currentUser, 'CREATE_USERS')
        && hasFeaturePermission(currentUser, 'CREATE_ORGANIZATIONS'),
      canEditOwnProfile: Boolean(currentUser?.id),
      canEditOwnOrganization:
        hasFeaturePermission(currentUser, 'UPDATE_ORGANIZATIONS')
        && getRoleScope(currentUser) === ROLE_SCOPES.ORGANIZATION,
      canAssignPrincipal: manageableRoleNames.includes(ROLE_NAMES.PRINCIPAL),
      canAssignDirector: manageableRoleNames.includes(ROLE_NAMES.DIRECTOR),
    };
  }
}

export default IamCapabilitiesService;
