import { Inject } from '@nestjs/common';
import { CommandHandler, type EventBus, type ICommandHandler } from '@nestjs/cqrs';
import { NotFoundException } from '@modules/shared/domain/domain-exception';
import { CacheService, CachePrefix } from '@modules/shared/infrastructure/cache.service';
import { LISTING_REPOSITORY, type IListingRepository } from '../../../domain/repositories/listing.repository';
import { ModerateListingCommand } from './moderate-listing.command';

@CommandHandler(ModerateListingCommand)
export class ModerateListingHandler implements ICommandHandler<ModerateListingCommand> {
  constructor(
    @Inject(LISTING_REPOSITORY) private readonly listingRepo: IListingRepository,
    private readonly eventBus: EventBus,
    private readonly cache: CacheService,
  ) {}

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

    if (command.moderationScore !== undefined) {
      listing.setModerationScore(command.moderationScore, command.notes);
    }

    if (command.action === 'approve') {
      listing.approve();
    } else {
      listing.reject(command.notes ?? 'Bị từ chối bởi moderator');
    }

    await this.listingRepo.update(listing);

    const events = listing.clearDomainEvents();
    for (const event of events) {
      this.eventBus.publish(event);
    }

    await Promise.all([
      this.cache.invalidate(CacheService.buildKey(CachePrefix.LISTING, command.listingId)),
      this.cache.invalidateByPrefix(CachePrefix.SEARCH),
    ]);

    return { status: listing.status };
  }
}
