import { Injectable } from '@nestjs/common';
import type { Scope } from 'shared-auth';

/**
 * Resolves the portal-side scopes for a user being signed in.
 *
 * Per [ADR-0025 §"Sources of truth — apf_portal-side `user_scopes`
 * table"](../../../../docs/decisions/0025-authorization-model-privileges-roles-scopes.md),
 * scopes are *not* carried by Entra: they will live in a portal
 * `user_scopes` Prisma table (proposed ADR-0026), queried by Entra
 * `oid` at sign-in. Each row materialises one `Scope` entry on the
 * session principal.
 *
 * The seam is here in v1 so the next PR replaces only the
 * implementation, leaving the call-site in `PrincipalBuilder`
 * untouched. The v1 implementation (`StubScopeResolver`) always
 * returns `[{ kind: 'unrestricted' }]` per ADR-0025 §331 — until
 * the Prisma table lands the test tenant runs against a single
 * "see everything" scope; the absence of fine-grained scoping is
 * acceptable because guards consuming `@RequireScope` are not in
 * the codebase yet.
 */
export abstract class ScopeResolver {
  abstract resolve(input: { entraOid: string }): Promise<ReadonlyArray<Scope>>;
}

/**
 * v1 stub — returns `unrestricted` for every user. Per ADR-0025
 * §"Sources of truth — apf_portal-side `user_scopes` table" the
 * real implementation queries `user_scopes WHERE userId = ?`; that
 * lands with the `Person` + `User` schema (proposed ADR-0026) and
 * the seed PR that follows.
 *
 * Deliberately not an in-memory hard-coded persona-keyed map: the
 * 19 test personas have *intended* scopes (see
 * `notes/test-tenant-role-assignments.md`) but those scopes have
 * no guard consuming them yet, so per-persona stub data would be
 * write-only documentation. When ADR-0026 lands, the seed PR
 * populates `user_scopes`; this class is replaced by a
 * Prisma-backed implementation in the same change.
 */
@Injectable()
export class StubScopeResolver extends ScopeResolver {
  override resolve(): Promise<ReadonlyArray<Scope>> {
    return Promise.resolve([{ kind: 'unrestricted' }]);
  }
}
