import { Inject, InternalServerErrorException } from '@nestjs/common';
import { CommandHandler, EventBus, type ICommandHandler } from '@nestjs/cqrs';
import { createId } from '@paralleldrive/cuid2';
import { DomainException, NotFoundException, PrismaService, LoggerService } from '@modules/shared';
import { InquiryEntity } from '../../../domain/entities/inquiry.entity';
import { INQUIRY_REPOSITORY, type IInquiryRepository } from '../../../domain/repositories/inquiry.repository';
import { SanitizeHtmlService } from '../../services/sanitize-html.service';
import { CreateInquiryCommand } from './create-inquiry.command';

export interface CreateInquiryResult {
  id: string;
  listingId: string;
  createdAt: string;
}

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

  async execute(command: CreateInquiryCommand): Promise<CreateInquiryResult> {
    try {
      // Validate listing exists
      const listing = await this.prisma.listing.findUnique({
        where: { id: command.listingId },
        select: { id: true },
      });
      if (!listing) {
        throw new NotFoundException('Listing', command.listingId);
      }

      const id = createId();
      const sanitizedMessage = this.sanitizer.sanitizeInquiryMessage(command.message);
      const inquiry = InquiryEntity.createNew(
        id,
        command.listingId,
        command.userId,
        sanitizedMessage,
        command.phone,
      );

      await this.inquiryRepo.save(inquiry);

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

      this.logger.log(`Inquiry ${id} created by user ${command.userId} for listing ${command.listingId}`, 'CreateInquiryHandler');

      return {
        id,
        listingId: command.listingId,
        createdAt: inquiry.createdAt.toISOString(),
      };
    } catch (error) {
      if (error instanceof DomainException) throw error;
      this.logger.error(
        `Failed to create inquiry: ${error instanceof Error ? error.message : String(error)}`,
        error instanceof Error ? error.stack : undefined,
        'CreateInquiryHandler',
      );
      throw new InternalServerErrorException('Lỗi khi tạo yêu cầu tư vấn');
    }
  }
}
