import { Module } from '@nestjs/common';
import { CqrsModule } from '@nestjs/cqrs';
import { JwtModule } from '@nestjs/jwt';
import { PassportModule } from '@nestjs/passport';
import { LoginUserHandler } from './application/commands/login-user/login-user.handler';
import { RefreshTokenHandler } from './application/commands/refresh-token/refresh-token.handler';
import { RegisterUserHandler } from './application/commands/register-user/register-user.handler';
import { VerifyKycHandler } from './application/commands/verify-kyc/verify-kyc.handler';
import { GetAgentByUserIdHandler } from './application/queries/get-agent-by-user-id/get-agent-by-user-id.handler';
import { GetProfileHandler } from './application/queries/get-profile/get-profile.handler';
import { REFRESH_TOKEN_REPOSITORY } from './domain/repositories/refresh-token.repository';
import { USER_REPOSITORY } from './domain/repositories/user.repository';
import { PrismaRefreshTokenRepository } from './infrastructure/repositories/prisma-refresh-token.repository';
import { PrismaUserRepository } from './infrastructure/repositories/prisma-user.repository';
import { OAuthService } from './infrastructure/services/oauth.service';
import { TokenService } from './infrastructure/services/token.service';
import { GoogleOAuthStrategy } from './infrastructure/strategies/google-oauth.strategy';
import { JwtStrategy } from './infrastructure/strategies/jwt.strategy';
import { LocalStrategy } from './infrastructure/strategies/local.strategy';
import { ZaloOAuthStrategy } from './infrastructure/strategies/zalo-oauth.strategy';
import { AuthController } from './presentation/controllers/auth.controller';
import { OAuthController } from './presentation/controllers/oauth.controller';

const CommandHandlers = [
  RegisterUserHandler,
  LoginUserHandler,
  RefreshTokenHandler,
  VerifyKycHandler,
];

const QueryHandlers = [GetProfileHandler, GetAgentByUserIdHandler];

@Module({
  imports: [
    CqrsModule,
    PassportModule,
    JwtModule.register({
      secret: (() => {
        const secret = process.env['JWT_SECRET'];
        if (!secret) {
          throw new Error('JWT_SECRET environment variable is required');
        }
        return secret;
      })(),
      signOptions: { expiresIn: '15m', audience: 'goodgo-api', issuer: 'goodgo-platform' },
    }),
  ],
  controllers: [AuthController, OAuthController],
  providers: [
    // Repositories
    { provide: USER_REPOSITORY, useClass: PrismaUserRepository },
    { provide: REFRESH_TOKEN_REPOSITORY, useClass: PrismaRefreshTokenRepository },

    // Strategies
    JwtStrategy,
    LocalStrategy,
    GoogleOAuthStrategy,
    ZaloOAuthStrategy,

    // Services
    TokenService,
    OAuthService,

    // CQRS
    ...CommandHandlers,
    ...QueryHandlers,
  ],
  exports: [TokenService, OAuthService, USER_REPOSITORY],
})
export class AuthModule {}
