import { InternalServerErrorException } from '@nestjs/common';
import { CommandHandler, type ICommandHandler } from '@nestjs/cqrs';
import { Prisma } from '@prisma/client';
import { LoggerService, PrismaService, DomainException, NotFoundException } from '@modules/shared';
import { ForceDeleteUserCommand } from './force-delete-user.command';

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

  async execute(command: ForceDeleteUserCommand): Promise<{ message: string }> {
    try {
      const user = await this.prisma.user.findUnique({ where: { id: command.userId } });
      if (!user) throw new NotFoundException('User', command.userId);
      if (user.deletedAt) return { message: 'Tài khoản đã bị xóa' };

      await this.anonymizeAndDelete(command.userId);

      this.logger.log(
        `User ${command.userId} force-deleted by admin ${command.adminId}: ${command.reason}`,
        'ForceDeleteUserHandler',
      );

      return { message: 'Tài khoản đã bị xóa vĩnh viễn' };
    } catch (error) {
      if (error instanceof DomainException) throw error;
      this.logger.error(
        `Failed to force delete user: ${error instanceof Error ? error.message : error}`,
        error instanceof Error ? error.stack : undefined,
        this.constructor.name,
      );
      throw new InternalServerErrorException('Không thể xóa vĩnh viễn tài khoản người dùng');
    }
  }

  private async anonymizeAndDelete(userId: string): Promise<void> {
    const now = new Date();
    const anonEmail = `deleted_${userId}@removed.local`;
    const anonName = 'Người dùng đã xóa';
    const anonPhone = `deleted_${userId.slice(0, 10)}`;

    await this.prisma.$transaction(async (tx) => {
      // 1. Anonymize user PII
      await tx.user.update({
        where: { id: userId },
        data: {
          email: anonEmail,
          phone: anonPhone,
          fullName: anonName,
          passwordHash: null,
          avatarUrl: null,
          kycData: Prisma.DbNull,
          kycStatus: 'NONE',
          isActive: false,
          deletedAt: now,
          deletionScheduledAt: null,
        },
      });

      // 2. Delete auth tokens (cascaded by DB, but explicit for safety)
      await tx.refreshToken.deleteMany({ where: { userId } });
      await tx.oAuthAccount.deleteMany({ where: { userId } });

      // 3. Anonymize agent if exists
      await tx.agent.updateMany({
        where: { userId },
        data: { isVerified: false, agency: null, bio: null, serviceAreas: [] },
      });

      // 4. Expire active listings
      await tx.listing.updateMany({
        where: { sellerId: userId, status: { in: ['ACTIVE', 'PENDING_REVIEW'] } },
        data: { status: 'EXPIRED' },
      });

      // 5. Cancel active subscription
      await tx.subscription.updateMany({
        where: { userId, status: 'ACTIVE' },
        data: { status: 'CANCELLED', cancelledAt: now },
      });

      // 6. Delete personal data that has no audit requirement
      await tx.review.deleteMany({ where: { userId } });
      await tx.inquiry.deleteMany({ where: { userId } });
      await tx.savedSearch.deleteMany({ where: { userId } });
      await tx.notificationLog.deleteMany({ where: { userId } });

      // 7. Payments & transactions are kept for audit (already anonymized via user PII removal)
    });
  }
}
