import { Inject, InternalServerErrorException } from '@nestjs/common';
import { CommandHandler, type ICommandHandler } from '@nestjs/cqrs';
import { LoggerService, DomainException, UnauthorizedException } from '@modules/shared';
import { USER_REPOSITORY, type IUserRepository } from '../../../domain/repositories/user.repository';
import { TokenService, type TokenPair } from '../../../infrastructure/services/token.service';
import { RefreshTokenCommand } from './refresh-token.command';

@CommandHandler(RefreshTokenCommand)
export class RefreshTokenHandler implements ICommandHandler<RefreshTokenCommand> {
  constructor(
    private readonly tokenService: TokenService,
    @Inject(USER_REPOSITORY) private readonly userRepo: IUserRepository,
    private readonly logger: LoggerService,
  ) {}

  async execute(command: RefreshTokenCommand): Promise<TokenPair> {
    try {
      let rotated: Awaited<ReturnType<TokenService['rotateRefreshToken']>>;
      try {
        rotated = await this.tokenService.rotateRefreshToken(command.refreshToken);
      } catch (error) {
        this.logger.error(
          `Token rotation failed: ${error instanceof Error ? error.message : error}`,
          error instanceof Error ? error.stack : undefined,
          'RefreshTokenHandler',
        );
        throw new UnauthorizedException('Không thể làm mới phiên đăng nhập');
      }

      if (!rotated) {
        throw new UnauthorizedException('Refresh token không hợp lệ hoặc đã hết hạn');
      }

      const user = await this.userRepo.findById(rotated.userId);
      if (!user || !user.isActive) {
        throw new UnauthorizedException('Tài khoản không tồn tại hoặc đã bị vô hiệu hóa');
      }

      const accessToken = this.tokenService.generateAccessToken({
        sub: user.id,
        phone: user.phone.value,
        role: user.role,
      });

      return {
        accessToken,
        refreshToken: rotated.refreshToken,
        expiresIn: 900,
      };
    } catch (error) {
      if (error instanceof DomainException) throw error;
      this.logger.error(
        `Failed to refresh token: ${error instanceof Error ? error.message : error}`,
        error instanceof Error ? error.stack : undefined,
        this.constructor.name,
      );
      throw new InternalServerErrorException('Không thể làm mới phiên đăng nhập');
    }
  }
}
