import { Module } from '@nestjs/common';
import { SentryModule } from '@sentry/nestjs/setup';
import { ConfigModule } from '@nestjs/config';
import { ScheduleModule } from '@nestjs/schedule';
import { APP_GUARD, APP_INTERCEPTOR, APP_PIPE } from '@nestjs/core';
import { ZodSerializerInterceptor, ZodValidationPipe } from 'nestjs-zod';
import { configValidationSchema, loadConfig } from './config/configuration';
import { PrismaModule } from './prisma/prisma.module';
import { RedisModule } from './redis/redis.module';
import { AlertingModule } from './common/alerting/alerting.module';
import { AuthModule } from './modules/auth/auth.module';
import { FactsModule } from './modules/facts/facts.module';
import { ClinicalSignalsModule } from './modules/clinical-signals/clinical-signals.module';
import { SyncModule } from './modules/sync/sync.module';
import { PatientModule } from './modules/patient/patient.module';
import { PersonaModule } from './modules/persona/persona.module';
import { PlanModule } from './modules/plan/plan.module';
import { PlanAggregateModule } from './modules/plan-aggregate/plan-aggregate.module';
import { AiModule } from './modules/ai/ai.module';
import { RealtimeCoachModule } from './modules/realtime-coach/realtime-coach.module';
import { AdminModule } from './modules/admin/admin.module';
import { McpModule } from './modules/mcp/mcp.module';
import { AssistantModule } from './modules/assistant/assistant.module';
import { WeixinAibotModule } from './modules/weixin-aibot/weixin-aibot.module';
import { QueuesModule } from './queues/queues.module';
import { QueuesBullBoardModule } from './queues/bull-board.module';
import { JwtAuthGuard } from './common/guards/jwt-auth.guard';
import { PermissionsGuard } from './common/guards/permissions.guard';
import { TenantScopeInterceptor } from './common/interceptors/tenant-scope.interceptor';
import { WrapResponseInterceptor } from './common/interceptors/wrap-response.interceptor';
import { HealthController } from './health.controller';

@Module({
  imports: [
    // Sentry:注册在最前(官方要求),配合 main.ts 首行的 ./instrument 提供请求级 tracing。
    SentryModule.forRoot(),
    ConfigModule.forRoot({
      isGlobal: true,
      load: [loadConfig],
      validationSchema: configValidationSchema,
      validationOptions: { abortEarly: false, allowUnknown: true },
    }),
    ScheduleModule.forRoot(),
    PrismaModule,
    RedisModule,
    QueuesModule,
    // Bull Board 队列面板 —— **默认不挂载**,设 PAC_BULL_BOARD=1 才开(见 bull-board.module.ts)。
    // 2026-08-05:实测它在生产上是公网无鉴权可读可写的入口,而平时没人用 → 默认关掉最省事。
    ...(process.env.PAC_BULL_BOARD === '1' ? [QueuesBullBoardModule] : []),
    AlertingModule,
    AuthModule,
    FactsModule,
    // @Global —— 摄入管线 / 画像特征 / 重扫 CLI 三处都要,放前面保证 SyncModule 解析时已就绪
    ClinicalSignalsModule,
    SyncModule,
    PatientModule,
    PersonaModule,
    PlanModule,
    AiModule,
    RealtimeCoachModule,
    McpModule,
    AssistantModule,
    WeixinAibotModule,
    AdminModule,
    PlanAggregateModule,
  ],
  controllers: [HealthController],
  providers: [
    { provide: APP_PIPE, useClass: ZodValidationPipe },
    { provide: APP_GUARD, useClass: JwtAuthGuard },
    { provide: APP_GUARD, useClass: PermissionsGuard },
    { provide: APP_INTERCEPTOR, useClass: TenantScopeInterceptor },
    // Order matters on the response leg (Nest reverses registration):
    //   handler → ZodSerializer (validate inner shape) → Wrap (envelope) → out
    // → register Wrap BEFORE Zod here.
    { provide: APP_INTERCEPTOR, useClass: WrapResponseInterceptor },
    { provide: APP_INTERCEPTOR, useClass: ZodSerializerInterceptor },
  ],
})
export class AppModule {}
