import { Inject, InternalServerErrorException } from '@nestjs/common';
// eslint-disable-next-line @typescript-eslint/consistent-type-imports -- NestJS DI requires value imports for emitDecoratorMetadata
import { CommandHandler, EventBus, ICommandHandler } from '@nestjs/cqrs';
// eslint-disable-next-line @typescript-eslint/consistent-type-imports -- NestJS DI requires value imports for emitDecoratorMetadata
import { DomainException, ForbiddenException, NotFoundException, LoggerService } from '@modules/shared';
import { REVIEW_REPOSITORY, type IReviewRepository } from '../../../domain/repositories/review.repository';
import { DeleteReviewCommand } from './delete-review.command';

@CommandHandler(DeleteReviewCommand)
export class DeleteReviewHandler implements ICommandHandler<DeleteReviewCommand> {
  constructor(
    @Inject(REVIEW_REPOSITORY) private readonly reviewRepo: IReviewRepository,
    private readonly eventBus: EventBus,
    private readonly logger: LoggerService,
  ) {}

  async execute(command: DeleteReviewCommand): Promise<void> {
    try {
      const review = await this.reviewRepo.findById(command.reviewId);
      if (!review) {
        throw new NotFoundException('Review', command.reviewId);
      }

      if (review.userId !== command.userId) {
        throw new ForbiddenException('Bạn chỉ có thể xóa đánh giá của chính mình');
      }

      review.markDeleted();
      await this.reviewRepo.delete(command.reviewId);

      // Publish domain events
      const events = review.clearDomainEvents();
      for (const event of events) {
        this.eventBus.publish(event);
      }

      this.logger.log(`Review ${command.reviewId} deleted by user ${command.userId}`, 'DeleteReviewHandler');
    } catch (error) {
      if (error instanceof DomainException) throw error;
      this.logger.error(
        `Failed to delete review: ${error instanceof Error ? error.message : String(error)}`,
        error instanceof Error ? error.stack : undefined,
        'DeleteReviewHandler',
      );
      throw new InternalServerErrorException('Lỗi khi xóa đánh giá');
    }
  }
}
