import { Module, Global } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { JwtModule } from '@nestjs/jwt';
import { HttpModule } from '@nestjs/axios';
import { ScheduleModule } from '@nestjs/schedule';
import { APP_FILTER, APP_INTERCEPTOR, APP_GUARD } from '@nestjs/core';

// Config
import {
  appConfig,
  databaseConfig,
  jwtConfig,
  redisConfig,
  kafkaConfig,
  smsConfig,
  walletConfig,
} from '@/config';

// Controllers
import { UserAccountController } from '@/api/controllers/user-account.controller';
import { HealthController } from '@/api/controllers/health.controller';
import { ReferralsController } from '@/api/controllers/referrals.controller';
import { AuthController } from '@/api/controllers/auth.controller';
import { TotpController } from '@/api/controllers/totp.controller';
import { InternalController } from '@/api/controllers/internal.controller';
import { KycController, AdminKycController } from '@/api/controllers/kyc.controller';
import {
  PendingActionController,
  AdminPendingActionController,
} from '@/api/controllers/pending-action.controller';

// Application Services
import { UserApplicationService } from '@/application/services/user-application.service';
import { TokenService } from '@/application/services/token.service';
import { TotpService } from '@/application/services/totp.service';
import { KycApplicationService } from '@/application/services/kyc-application.service';
import { PendingActionService } from '@/application/services/pending-action.service';
import { BlockchainWalletHandler } from '@/application/event-handlers/blockchain-wallet.handler';
import { MpcKeygenCompletedHandler } from '@/application/event-handlers/mpc-keygen-completed.handler';
import { WalletRetryTask } from '@/application/tasks/wallet-retry.task';

// Domain Services
import {
  AccountSequenceGeneratorService,
  UserValidatorService,
} from '@/domain/services';
import { USER_ACCOUNT_REPOSITORY } from '@/domain/repositories/user-account.repository.interface';
import { MPC_KEY_SHARE_REPOSITORY } from '@/domain/repositories/mpc-key-share.repository.interface';

// Infrastructure
import { PrismaService } from '@/infrastructure/persistence/prisma/prisma.service';
import { UserAccountRepositoryImpl } from '@/infrastructure/persistence/repositories/user-account.repository.impl';
import { MpcKeyShareRepositoryImpl } from '@/infrastructure/persistence/repositories/mpc-key-share.repository.impl';
import { RedisService } from '@/infrastructure/redis/redis.service';
import { EventPublisherService } from '@/infrastructure/kafka/event-publisher.service';
import { MpcEventConsumerService } from '@/infrastructure/kafka/mpc-event-consumer.service';
import { BlockchainEventConsumerService } from '@/infrastructure/kafka/blockchain-event-consumer.service';
import { SmsService } from '@/infrastructure/external/sms/sms.service';
import { EmailService } from '@/infrastructure/external/email/email.service';
import { BlockchainClientService } from '@/infrastructure/external/blockchain/blockchain-client.service';
import {
  MpcClientService,
  MpcWalletService,
} from '@/infrastructure/external/mpc';
import { StorageService } from '@/infrastructure/external/storage/storage.service';
import { AliyunKycProvider } from '@/infrastructure/external/kyc/aliyun-kyc.provider';

// Shared
import {
  GlobalExceptionFilter,
  TransformInterceptor,
} from '@/shared/filters/global-exception.filter';
import { JwtAuthGuard } from '@/shared/guards/jwt-auth.guard';

// ============ Infrastructure Module ============
@Global()
@Module({
  imports: [
    ConfigModule,
    HttpModule.register({
      timeout: 300000,
      maxRedirects: 5,
    }),
  ],
  providers: [
    PrismaService,
    RedisService,
    EventPublisherService,
    MpcEventConsumerService,
    BlockchainEventConsumerService,
    SmsService,
    EmailService,
    MpcClientService,
    MpcWalletService,
    BlockchainClientService,
    StorageService,
    AliyunKycProvider,
    { provide: MPC_KEY_SHARE_REPOSITORY, useClass: MpcKeyShareRepositoryImpl },
  ],
  exports: [
    PrismaService,
    RedisService,
    EventPublisherService,
    MpcEventConsumerService,
    BlockchainEventConsumerService,
    SmsService,
    EmailService,
    MpcClientService,
    MpcWalletService,
    BlockchainClientService,
    StorageService,
    AliyunKycProvider,
    MPC_KEY_SHARE_REPOSITORY,
  ],
})
export class InfrastructureModule {}

// ============ Domain Module ============
@Module({
  imports: [InfrastructureModule],
  providers: [
    { provide: USER_ACCOUNT_REPOSITORY, useClass: UserAccountRepositoryImpl },
    AccountSequenceGeneratorService,
    UserValidatorService,
  ],
  exports: [
    USER_ACCOUNT_REPOSITORY,
    AccountSequenceGeneratorService,
    UserValidatorService,
  ],
})
export class DomainModule {}

// ============ Application Module ============
@Module({
  imports: [DomainModule, InfrastructureModule, ScheduleModule.forRoot()],
  providers: [
    UserApplicationService,
    TokenService,
    TotpService,
    KycApplicationService,
    PendingActionService,
    // Event Handlers - 通过注入到 UserApplicationService 来确保它们被初始化
    BlockchainWalletHandler,
    MpcKeygenCompletedHandler,
    // Tasks - 定时任务
    WalletRetryTask,
  ],
  exports: [UserApplicationService, TokenService, TotpService, KycApplicationService, PendingActionService],
})
export class ApplicationModule {}

// ============ API Module ============
@Module({
  imports: [ApplicationModule, InfrastructureModule],
  controllers: [
    HealthController,
    UserAccountController,
    ReferralsController,
    AuthController,
    TotpController,
    InternalController,
    KycController,
    AdminKycController,
    PendingActionController,
    AdminPendingActionController,
  ],
  providers: [UserAccountRepositoryImpl],
})
export class ApiModule {}

// ============ App Module ============
@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      load: [
        appConfig,
        databaseConfig,
        jwtConfig,
        redisConfig,
        kafkaConfig,
        smsConfig,
        walletConfig,
      ],
    }),
    JwtModule.registerAsync({
      global: true,
      inject: [ConfigService],
      useFactory: (configService: ConfigService) => ({
        secret: configService.get<string>('JWT_SECRET'),
        signOptions: {
          expiresIn: configService.get<string>('JWT_ACCESS_EXPIRES_IN', '2h'),
        },
      }),
    }),
    InfrastructureModule,
    DomainModule,
    ApplicationModule,
    ApiModule,
  ],
  providers: [
    { provide: APP_FILTER, useClass: GlobalExceptionFilter },
    { provide: APP_INTERCEPTOR, useClass: TransformInterceptor },
    { provide: APP_GUARD, useClass: JwtAuthGuard },
  ],
})
export class AppModule {}
