import type { ActorScope, SecurityContext } from '../auth/context.js';
import { EMPTY_SCOPE } from '../auth/context.js';
import type { Permission } from '../auth/permissions.js';

/**
 * Test helpers for building a `SecurityContext`.
 *
 * Exported from the package (rather than kept in a test folder) so the
 * integration and E2E suites in `apps/web` can build the same actors without
 * duplicating the shape.
 */
export interface TestActorOptions {
  readonly userId?: string;
  readonly institutionId?: string;
  readonly email?: string;
  readonly displayName?: string;
  readonly roles?: readonly string[];
  readonly permissions?: readonly Permission[];
  readonly isSuperAdmin?: boolean;
  readonly scope?: Partial<ActorScope>;
}

export function testActor(options: TestActorOptions = {}): SecurityContext {
  return {
    userId: options.userId ?? 'user-test',
    institutionId: options.institutionId ?? 'institution-test',
    email: options.email ?? 'test@example.local',
    displayName: options.displayName ?? 'Test Actor',
    roles: options.roles ?? [],
    permissions: new Set(options.permissions ?? []),
    isSuperAdmin: options.isSuperAdmin ?? false,
    scope: { ...EMPTY_SCOPE, ...(options.scope ?? {}) },
    sessionId: 'session-test',
    ipAddress: '127.0.0.1',
    userAgent: 'vitest',
  };
}

/** A Dean scoped to one college — the canonical scoped-staff actor. */
export function testDean(collegeIds: readonly string[], extra: TestActorOptions = {}): SecurityContext {
  return testActor({
    userId: 'user-dean',
    roles: ['DEAN'],
    permissions: [
      'application.read',
      'application.review',
      'application.approve',
      'student.read',
      'pre_registration.approve',
      'interview.evaluate',
      'faculty_load.manage',
    ],
    ...extra,
    scope: { collegeIds, ...(extra.scope ?? {}) },
  });
}

/** A Faculty member scoped to their assigned section offerings. */
export function testFaculty(
  sectionOfferingIds: readonly string[],
  extra: TestActorOptions = {},
): SecurityContext {
  return testActor({
    userId: 'user-faculty',
    roles: ['FACULTY'],
    permissions: ['student.read', 'grade.read', 'grade.encode', 'grade.submit', 'section.read'],
    ...extra,
    scope: {
      sectionOfferingIds,
      facultyProfileId: 'faculty-profile-1',
      ...(extra.scope ?? {}),
    },
  });
}

/** A Student, confined to their own record. */
export function testStudent(studentId: string, extra: TestActorOptions = {}): SecurityContext {
  return testActor({
    userId: 'user-student',
    roles: ['STUDENT'],
    permissions: [
      'self.profile.read',
      'self.enrollment.read',
      'self.grade.read',
      'self.finance.read',
      'document_request.create',
    ],
    ...extra,
    scope: { studentId, ...(extra.scope ?? {}) },
  });
}

/** A Registrar — institution-wide, with no narrowing assignment. */
export function testRegistrar(extra: TestActorOptions = {}): SecurityContext {
  return testActor({
    userId: 'user-registrar',
    roles: ['REGISTRAR'],
    permissions: [
      'student.read',
      'student.manage',
      'enrollment.read',
      'enrollment.review',
      'enrollment.approve',
      'grade.read',
      'grade.publish',
      'assessment.manage',
      'requirement.review',
    ],
    ...extra,
  });
}

/** A Cashier — financial permissions only, deliberately no academic ones. */
export function testCashier(extra: TestActorOptions = {}): SecurityContext {
  return testActor({
    userId: 'user-cashier',
    roles: ['CASHIER'],
    permissions: ['student.read', 'assessment.read', 'payment.read', 'payment.create'],
    ...extra,
  });
}

export function testSuperAdmin(extra: TestActorOptions = {}): SecurityContext {
  return testActor({
    userId: 'user-superadmin',
    roles: ['SUPERADMIN'],
    isSuperAdmin: true,
    ...extra,
  });
}
