import { Module } from '@nestjs/common';
import { assertJwksConfig } from '../config/check-jwks-config';
import { assertOboCacheEncryptionKey } from '../config/check-obo-cache-encryption-key';
import { AuthModule } from '../auth/auth.module';
import { RedisModule } from '../redis/redis.module';
import { BFF_SIGNING_KEY, buildBffSigningKey } from './bff-signing-key';
import { DownstreamTokenCache } from './downstream-token-cache.service';
import { OBO_CACHE_KEY } from './downstream.token';
import { JwksPublisher } from './jwks.publisher';
import { OboStrategy } from './strategies/obo.strategy';
import { SignedAssertionStrategy } from './strategies/signed-assertion.strategy';

/**
 * `DownstreamModule` — primitives for the downstream-API framework
 * per [ADR-0014](../../../../docs/decisions/0014-downstream-api-access-obo-pattern.md).
 *
 * **Scope (v1).** This module ships the auth-strategy primitives,
 * the OBO token cache, and the BFF's JWKS publishing endpoint. The
 * framework around them (`DownstreamApiClientFactory`, cockatiel
 * resilience stack, audience pre-check, error translation, OTel
 * custom spans) lands alongside the first concrete consumer per the
 * ADR's own guidance:
 *
 *   "Mitigated by writing the framework code only in the same
 *    iteration as the first concrete integration; until then, this
 *    ADR plus mock-driven unit tests on the strategies (OBO,
 *    signed-assertion) keep the design honest."
 *
 * What's exposed for the future integration to consume:
 *
 *   - `OboStrategy` (Entra-protected downstreams).
 *   - `SignedAssertionStrategy` (non-Entra downstreams).
 *   - `DownstreamTokenCache` (used internally by OboStrategy; exposed
 *     in case a future consumer wants direct cache management).
 *
 * Imports `AuthModule` for the shared `MSAL_CLIENT`, `RedisModule`
 * for the shared `ioredis` client.
 */
@Module({
  imports: [AuthModule, RedisModule],
  providers: [
    {
      provide: OBO_CACHE_KEY,
      useFactory: () => assertOboCacheEncryptionKey(),
    },
    {
      provide: BFF_SIGNING_KEY,
      useFactory: () => buildBffSigningKey(assertJwksConfig()),
    },
    DownstreamTokenCache,
    OboStrategy,
    SignedAssertionStrategy,
    JwksPublisher,
  ],
  // `JwksPublisher` is exported so `main.ts` can resolve it from the
  // Nest container and wire it into an Express-direct `GET
  // /.well-known/jwks.json` handler. The handler bypasses Nest's
  // path-to-regexp-based router because v8 doesn't cleanly route a
  // leading-dot segment to a bare-root URL.
  exports: [OboStrategy, SignedAssertionStrategy, DownstreamTokenCache, JwksPublisher],
})
export class DownstreamModule {}
