import { Inject, InternalServerErrorException } from '@nestjs/common';
import { CommandHandler, EventBus, type ICommandHandler } from '@nestjs/cqrs';
import { DomainException, ForbiddenException, NotFoundException, PrismaService, LoggerService } from '@modules/shared';
import { INQUIRY_REPOSITORY, type IInquiryRepository } from '../../../domain/repositories/inquiry.repository';
import { MarkInquiryReadCommand } from './mark-inquiry-read.command';

@CommandHandler(MarkInquiryReadCommand)
export class MarkInquiryReadHandler implements ICommandHandler<MarkInquiryReadCommand> {
  constructor(
    @Inject(INQUIRY_REPOSITORY) private readonly inquiryRepo: IInquiryRepository,
    private readonly eventBus: EventBus,
    private readonly prisma: PrismaService,
    private readonly logger: LoggerService,
  ) {}

  async execute(command: MarkInquiryReadCommand): Promise<void> {
    try {
      const inquiry = await this.inquiryRepo.findById(command.inquiryId);
      if (!inquiry) {
        throw new NotFoundException('Inquiry', command.inquiryId);
      }

      // Verify the requesting user is the listing's agent
      const listing = await this.prisma.listing.findUnique({
        where: { id: inquiry.listingId },
        select: { agentId: true },
      });
      if (!listing) {
        throw new NotFoundException('Listing', inquiry.listingId);
      }

      const agent = await this.prisma.agent.findUnique({
        where: { userId: command.agentUserId },
        select: { id: true },
      });
      if (!agent || listing.agentId !== agent.id) {
        throw new ForbiddenException('Bạn không có quyền đánh dấu yêu cầu tư vấn này');
      }

      inquiry.markAsRead();
      await this.inquiryRepo.markAsRead(command.inquiryId);

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

      this.logger.log(`Inquiry ${command.inquiryId} marked as read by agent ${command.agentUserId}`, 'MarkInquiryReadHandler');
    } catch (error) {
      if (error instanceof DomainException) throw error;
      this.logger.error(
        `Failed to mark inquiry as read: ${error instanceof Error ? error.message : String(error)}`,
        error instanceof Error ? error.stack : undefined,
        'MarkInquiryReadHandler',
      );
      throw new InternalServerErrorException('Lỗi khi đánh dấu đã đọc');
    }
  }
}
