import { Inject, InternalServerErrorException } from '@nestjs/common';
import { CommandHandler, EventBus, type ICommandHandler } from '@nestjs/cqrs';
import { DomainException, ForbiddenException, NotFoundException, PrismaService, LoggerService } from '@modules/shared';
import { type LeadStatus } from '../../../domain/entities/lead.entity';
import { LEAD_REPOSITORY, type ILeadRepository } from '../../../domain/repositories/lead.repository';
import { UpdateLeadStatusCommand } from './update-lead-status.command';

@CommandHandler(UpdateLeadStatusCommand)
export class UpdateLeadStatusHandler implements ICommandHandler<UpdateLeadStatusCommand> {
  constructor(
    @Inject(LEAD_REPOSITORY) private readonly leadRepo: ILeadRepository,
    private readonly eventBus: EventBus,
    private readonly prisma: PrismaService,
    private readonly logger: LoggerService,
  ) {}

  async execute(command: UpdateLeadStatusCommand): Promise<void> {
    try {
      // Look up agent by userId
      const agent = await this.prisma.agent.findUnique({
        where: { userId: command.agentUserId },
      });
      if (!agent) {
        throw new NotFoundException('Agent', command.agentUserId);
      }

      const lead = await this.leadRepo.findById(command.leadId);
      if (!lead) {
        throw new NotFoundException('Lead', command.leadId);
      }

      // Verify agent ownership
      if (lead.agentId !== agent.id) {
        throw new ForbiddenException('Bạn chỉ có thể cập nhật lead của chính mình');
      }

      lead.updateStatus(command.newStatus as LeadStatus);
      await this.leadRepo.update(lead);

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

      this.logger.log(`Lead ${command.leadId} status updated to ${command.newStatus} by agent ${agent.id}`, 'UpdateLeadStatusHandler');
    } catch (error) {
      if (error instanceof DomainException) throw error;
      this.logger.error(
        `Failed to update lead status: ${error instanceof Error ? error.message : String(error)}`,
        error instanceof Error ? error.stack : undefined,
        'UpdateLeadStatusHandler',
      );
      throw new InternalServerErrorException('Lỗi khi cập nhật trạng thái lead');
    }
  }
}
