import { InternalServerErrorException } from '@nestjs/common';
import { CommandHandler, type ICommandHandler } from '@nestjs/cqrs';
import { LoggerService, PrismaService, DomainException, NotFoundException, ValidationException } from '@modules/shared';
import { RequestUserDeletionCommand } from './request-user-deletion.command';

const DELETION_GRACE_PERIOD_DAYS = 30;

@CommandHandler(RequestUserDeletionCommand)
export class RequestUserDeletionHandler implements ICommandHandler<RequestUserDeletionCommand> {
  constructor(
    private readonly prisma: PrismaService,
    private readonly logger: LoggerService,
  ) {}

  async execute(command: RequestUserDeletionCommand): Promise<{ scheduledAt: Date }> {
    try {
      const user = await this.prisma.user.findUnique({ where: { id: command.userId } });
      if (!user) throw new NotFoundException('User', command.userId);
      if (user.deletedAt) throw new ValidationException('Tài khoản đã bị xóa');
      if (user.deletionScheduledAt) throw new ValidationException('Yêu cầu xóa đã tồn tại');

      const scheduledAt = new Date();
      scheduledAt.setDate(scheduledAt.getDate() + DELETION_GRACE_PERIOD_DAYS);

      await this.prisma.user.update({
        where: { id: command.userId },
        data: { deletionScheduledAt: scheduledAt, isActive: false },
      });

      // Revoke all refresh tokens
      await this.prisma.refreshToken.updateMany({
        where: { userId: command.userId, revokedAt: null },
        data: { revokedAt: new Date() },
      });

      this.logger.log(
        `User ${command.userId} deletion scheduled for ${scheduledAt.toISOString()}`,
        'RequestUserDeletionHandler',
      );

      return { scheduledAt };
    } catch (error) {
      if (error instanceof DomainException) throw error;
      this.logger.error(
        `Failed to request user deletion: ${error instanceof Error ? error.message : error}`,
        error instanceof Error ? error.stack : undefined,
        this.constructor.name,
      );
      throw new InternalServerErrorException('Không thể xử lý yêu cầu xóa tài khoản');
    }
  }
}
