import { Inject, InternalServerErrorException } from '@nestjs/common';
import { CommandHandler, EventBus, type ICommandHandler } from '@nestjs/cqrs';
import { LISTING_REPOSITORY, type IListingRepository } from '@modules/listings';
import { DomainException, NotFoundException, ValidationException, LoggerService } from '@modules/shared';
import { ListingApprovedEvent } from '../../../domain/events/listing-approved.event';
import { ApproveListingCommand } from './approve-listing.command';

export interface ApproveListingResult {
  listingId: string;
  status: string;
  message: string;
}

@CommandHandler(ApproveListingCommand)
export class ApproveListingHandler implements ICommandHandler<ApproveListingCommand> {
  constructor(
    @Inject(LISTING_REPOSITORY) private readonly listingRepo: IListingRepository,
    private readonly eventBus: EventBus,
    private readonly logger: LoggerService,
  ) {}

  async execute(command: ApproveListingCommand): Promise<ApproveListingResult> {
    try {
      const listing = await this.listingRepo.findById(command.listingId);
      if (!listing) {
        throw new NotFoundException('Listing không tồn tại');
      }

      if (listing.status !== 'PENDING_REVIEW') {
        throw new ValidationException(
          `Listing đang ở trạng thái ${listing.status}, chỉ có thể duyệt listing đang chờ duyệt`,
          { currentStatus: listing.status },
        );
      }

      listing.approve();

      if (command.moderationNotes) {
        listing.setModerationScore(1.0, command.moderationNotes);
      }

      await this.listingRepo.update(listing);

      this.eventBus.publish(
        new ListingApprovedEvent(listing.id, command.adminId, command.moderationNotes),
      );

      return {
        listingId: listing.id,
        status: 'ACTIVE',
        message: 'Listing đã được duyệt thành công',
      };
    } catch (error) {
      if (error instanceof DomainException) throw error;
      this.logger.error(
        `Failed to approve listing ${command.listingId}: ${error instanceof Error ? error.message : String(error)}`,
        error instanceof Error ? error.stack : undefined,
        'ApproveListingHandler',
      );
      throw new InternalServerErrorException('Lỗi khi duyệt listing');
    }
  }
}
