import { Inject } from '@nestjs/common';
import { CommandHandler, type ICommandHandler } from '@nestjs/cqrs';
import { ForbiddenException, NotFoundException } from '@modules/shared';
import { LISTING_REPOSITORY, type IListingRepository } from '../../../domain/repositories/listing.repository';
import { DeleteListingCommand } from './delete-listing.command';

@CommandHandler(DeleteListingCommand)
export class DeleteListingHandler implements ICommandHandler<DeleteListingCommand> {
  constructor(
    @Inject(LISTING_REPOSITORY) private readonly listingRepo: IListingRepository,
  ) {}

  async execute(command: DeleteListingCommand): Promise<void> {
    const listing = await this.listingRepo.findById(command.listingId);
    if (!listing) {
      throw new NotFoundException('Listing', command.listingId);
    }

    const isOwner = listing.sellerId === command.userId;
    const isAdmin = command.userRole === 'ADMIN';
    if (!isOwner && !isAdmin) {
      throw new ForbiddenException(
        'Chỉ người bán hoặc quản trị viên mới có thể xóa tin đăng',
      );
    }

    // Atomicity contract: IListingRepository.delete MUST wrap all side-effects
    // (savedListing, inquiry, priceHistory, order, transaction, listing) in a
    // single prisma.$transaction([...]) so that a failure in any step rolls back
    // the entire delete. See PrismaListingRepository.delete for the concrete
    // implementation. Tests: delete-listing.handler.spec.ts (rollback case).
    await this.listingRepo.delete(command.listingId);
  }
}
