import {
  Module,
  NestModule,
  MiddlewareConsumer,
  OnModuleInit,
  Logger,
} from "@nestjs/common";
import { APP_GUARD } from "@nestjs/core";
import { IamModule } from "./iam/iam.module.js";
import { HealthModule } from "./shared/health/health.module.js";
import { PermissionGuard } from "./middleware/permission.guard.js";
import { AuthMiddleware } from "./middleware/auth.middleware.js";
import { LifecycleService } from "./shared/lifecycle/lifecycle.service.js";
import { OutboxModule } from "@edu/shared-ts/outbox";
import { getDbInstance } from "./config/database.js";
import {
  getKafkaProducer,
  connectKafkaProducer,
  IAM_KAFKA_TOPICS,
} from "./config/kafka.js";

/**
 * IAM 根模块。
 *
 * 装配：
 * - IamModule（业务）
 * - HealthModule（健康检查）
 * - OutboxModule（事务性事件发布，I5 裁决）
 * - AuthMiddleware（从 Gateway 注入的 x-user-* 头部解析用户身份）
 * - PermissionGuard（APP_GUARD，DB 驱动 + Redis 缓存，I3 裁决）
 */
@Module({
  imports: [
    IamModule,
    HealthModule,
    OutboxModule.forRoot({
      config: {
        tableName: "iam_outbox",
        kafkaTopic: IAM_KAFKA_TOPICS.USER_EVENTS,
        pollIntervalMs: 1000,
        batchSize: 20,
        maxRetryCount: 5,
        retryBackoffMs: 1000,
      },
      db: getDbInstance(),
      kafkaProducer: getKafkaProducer(),
    }),
  ],
  providers: [
    { provide: APP_GUARD, useClass: PermissionGuard },
    LifecycleService,
  ],
})
export class AppModule implements NestModule, OnModuleInit {
  private readonly logger = new Logger(AppModule.name);

  async onModuleInit(): Promise<void> {
    // 连接 Kafka producer（Outbox 投递前置依赖）
    try {
      await connectKafkaProducer();
      this.logger.log("Kafka producer connected");
    } catch (error) {
      this.logger.error(
        `Kafka producer connect failed: ${error instanceof Error ? error.message : String(error)}`,
      );
    }
  }

  configure(consumer: MiddlewareConsumer): void {
    // AuthMiddleware 应用于需要鉴权的 /v1/iam 路由
    // 公开端点（register/login/refresh/jwks/health/metrics）不走此中间件
    consumer
      .apply(AuthMiddleware)
      .forRoutes(
        "v1/iam/me",
        "v1/iam/logout",
        "v1/iam/viewports",
        "v1/iam/permissions/effective",
        "v1/iam/children",
        "v1/iam/roles",
        "v1/iam/permissions",
        "v1/iam/audit",
      );
  }
}
