import { Global, Module, type OnModuleInit } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { ContextAttestationVerifier } from './context-attestation';
import { PrismaClientRegistry, PrismaNonceStore, JwksPublicKeyResolver } from './attestation-stores';
import { ContextAttestationGuard } from './context-attestation.guard';

/**
 * Wires the context-attestation trust layer into DI and exposes the guard globally so any
 * controller can enforce the three-proof gate. Also dev-seeds a registered client so locally
 * minted attestations verify (prod registers clients out-of-band).
 */
@Global()
@Module({
  providers: [
    PrismaClientRegistry,
    PrismaNonceStore,
    JwksPublicKeyResolver,
    {
      provide: ContextAttestationVerifier,
      useFactory: (reg: PrismaClientRegistry, nonces: PrismaNonceStore, keys: JwksPublicKeyResolver) =>
        new ContextAttestationVerifier(reg, nonces, { audience: process.env.IIOS_ATTESTATION_AUDIENCE ?? 'iios-core' }, keys),
      inject: [PrismaClientRegistry, PrismaNonceStore, JwksPublicKeyResolver],
    },
    ContextAttestationGuard,
  ],
  exports: [ContextAttestationVerifier, ContextAttestationGuard],
})
export class AttestationModule implements OnModuleInit {
  constructor(private readonly prisma: PrismaService) {}

  /** Dev seed: register the CRM support client so an attestation signed with the shared dev
   *  secret verifies locally. Gated by IIOS_DEV_TOKENS + IIOS_ATTESTATION_DEV_SECRET; best-effort. */
  async onModuleInit(): Promise<void> {
    if (process.env.IIOS_DEV_TOKENS !== '1') return;
    const secret = process.env.IIOS_ATTESTATION_DEV_SECRET;
    if (!secret) return;
    await this.prisma.iiosClientRegistry
      .upsert({
        where: { clientId: 'appshell-crm' },
        create: { clientId: 'appshell-crm', clientType: 'APPSHELL', allowedAppIds: ['crm-web'], attestSecret: secret, status: 'ACTIVE' },
        update: { clientType: 'APPSHELL', attestSecret: secret, allowedAppIds: ['crm-web'], status: 'ACTIVE' },
      })
      .catch(() => undefined);
  }
}
