import { Inject, InternalServerErrorException } from '@nestjs/common';
import { CommandHandler, type ICommandHandler } from '@nestjs/cqrs';
import { DomainException, LoggerService, ValidationException } from '@modules/shared';
import { USER_REPOSITORY, type IUserRepository } from '../../../domain/repositories/user.repository';
import { MfaService } from '../../../infrastructure/services/mfa.service';
import { VerifyMfaSetupCommand } from './verify-mfa-setup.command';

export interface VerifyMfaSetupResultDto {
  backupCodes: string[];
  backupCodeCount: number;
  message: string;
}

@CommandHandler(VerifyMfaSetupCommand)
export class VerifyMfaSetupHandler implements ICommandHandler<VerifyMfaSetupCommand> {
  constructor(
    @Inject(USER_REPOSITORY) private readonly userRepo: IUserRepository,
    private readonly mfaService: MfaService,
    private readonly logger: LoggerService,
  ) {}

  async execute(command: VerifyMfaSetupCommand): Promise<VerifyMfaSetupResultDto> {
    try {
      const user = await this.userRepo.findById(command.userId);
      if (!user) {
        throw new ValidationException('Người dùng không tồn tại');
      }

      if (user.totpEnabled) {
        throw new ValidationException('MFA đã được bật');
      }

      if (!user.totpSecret) {
        throw new ValidationException('Chưa thiết lập MFA. Vui lòng gọi /auth/mfa/setup trước');
      }

      // Verify the TOTP code against the stored (pending) secret
      const isValid = await this.mfaService.verifyTotp(command.totpCode, user.totpSecret);
      if (!isValid) {
        throw new ValidationException('Mã TOTP không hợp lệ. Vui lòng thử lại');
      }

      // Generate backup codes
      const { plainCodes, hashedCodes } = this.mfaService.generateBackupCodes();

      // Enable MFA
      await this.userRepo.updateMfaEnabled(
        command.userId,
        true,
        user.totpSecret,
        hashedCodes,
      );

      return {
        backupCodes: plainCodes,
        backupCodeCount: plainCodes.length,
        message: 'MFA đã được bật thành công. Vui lòng lưu mã backup an toàn',
      };
    } catch (error) {
      if (error instanceof DomainException) throw error;
      this.logger.error(
        `Failed to verify MFA setup: ${error instanceof Error ? error.message : error}`,
        error instanceof Error ? error.stack : undefined,
        this.constructor.name,
      );
      throw new InternalServerErrorException('Không thể xác nhận thiết lập MFA');
    }
  }
}
