import { Injectable } from '@nestjs/common';
import { CaslAbilityFactory } from '../authorization/casl-ability.factory';
import { CaslAction, SubjectName } from '../authorization/casl.constants';
import type { AgentToolContext } from '../agent-tools/agent-tool.types';
import type { StudentAccessScope } from './student-access-scope';

/**
 * Constructs a {@link StudentAccessScope} from the trusted server-side
 * principal carried in {@link AgentToolContext}.
 *
 * ## Scope rules
 *
 * | Condition | Scope |
 * |---|---|
 * | `isSuperAdmin` | `manageAll` |
 * | `class:edit` domain ability (`Update Class`) | `manageAll` |
 * | Everything else | `teacher(userId)` |
 *
 * These rules mirror the HTTP-layer logic so agent tools are consistent
 * with the web dashboard. The ability is constructed fresh from the
 * principal each time — callers cannot pre-forge it.
 */
@Injectable()
export class StudentAccessScopeFactory {
  constructor(private readonly abilityFactory: CaslAbilityFactory) {}

  /**
   * Build a scope from the authenticated context.
   *
   * The ability is constructed from the principal fields inside the context
   * — every call is a fresh derivation.
   */
  buildScope(context: AgentToolContext): StudentAccessScope {
    const ability = this.abilityFactory.createForUser({
      permissions: context.permissions,
      isSuperAdmin: context.isSuperAdmin,
    });

    if (context.isSuperAdmin) {
      return { type: 'manageAll' };
    }

    // class:edit (Update Class) grants full student scope
    if (ability.can(CaslAction.Update, SubjectName.Class)) {
      return { type: 'manageAll' };
    }

    return { type: 'teacher', userId: context.userId };
  }
}
