import { InternalServerErrorException } from '@nestjs/common';
import { CommandHandler, type ICommandHandler } from '@nestjs/cqrs';
import {
  ConflictException,
  DomainException,
  LoggerService,
  NotFoundException,
  PrismaService,
} from '@modules/shared';
import { UpgradeToAgentCommand } from './upgrade-to-agent.command';

export interface UpgradeToAgentResult {
  agentId: string;
  userId: string;
  isVerified: false;
}

@CommandHandler(UpgradeToAgentCommand)
export class UpgradeToAgentHandler
  implements ICommandHandler<UpgradeToAgentCommand>
{
  constructor(
    private readonly prisma: PrismaService,
    private readonly logger: LoggerService,
  ) {}

  async execute(command: UpgradeToAgentCommand): Promise<UpgradeToAgentResult> {
    try {
      const user = await this.prisma.user.findUnique({
        where: { id: command.userId },
        select: { id: true, role: true, agent: { select: { id: true } } },
      });

      if (!user) {
        throw new NotFoundException('User', command.userId);
      }

      if (user.role === 'AGENT') {
        throw new ConflictException('Tài khoản đã là đại lý');
      }

      if (user.role === 'ADMIN') {
        throw new ConflictException('Admin không cần nâng cấp đại lý');
      }

      if (user.agent) {
        throw new ConflictException('Hồ sơ đại lý đã tồn tại cho tài khoản này');
      }

      const agentId = await this.prisma.$transaction(async (tx) => {
        const agent = await tx.agent.create({
          data: {
            userId: command.userId,
            licenseNumber: command.licenseNumber,
            agency: command.agency,
            bio: command.bio,
            serviceAreas: command.serviceAreas ?? [],
            isVerified: false,
          },
          select: { id: true },
        });

        await tx.user.update({
          where: { id: command.userId },
          data: { role: 'AGENT' },
        });

        return agent.id;
      });

      this.logger.log(
        `User ${command.userId} upgraded to AGENT (agentId=${agentId})`,
        'UpgradeToAgentHandler',
      );

      return {
        agentId,
        userId: command.userId,
        isVerified: false,
      };
    } catch (error) {
      if (error instanceof DomainException) throw error;
      this.logger.error(
        `Failed to upgrade user ${command.userId} to agent: ${error instanceof Error ? error.message : error}`,
        error instanceof Error ? error.stack : undefined,
        this.constructor.name,
      );
      throw new InternalServerErrorException('Không thể nâng cấp tài khoản lên đại lý');
    }
  }
}
