import { PrismaClient, IdentityVerification, VerificationType, VerificationStatus } from '@prisma/client';

import { getPrismaClient } from '../config/database.config';
import { BaseRepository } from '../modules/common/repository';

/**
 * EN: Identity Verification repository for database operations
 * VI: Repository xác thực danh tính cho các thao tác database
 */
export class IdentityVerificationRepository extends BaseRepository<IdentityVerification, any, any> {
  constructor(prisma?: PrismaClient) {
    super(prisma || getPrismaClient(), 'identityVerification');
  }

  /**
   * EN: Find verification by token
   * VI: Tìm xác thực theo token
   */
  async findByToken(token: string): Promise<IdentityVerification | null> {
    return this.prisma.identityVerification.findUnique({
      where: { token },
      include: {
        user: {
          select: {
            id: true,
            email: true,
            username: true,
          },
        },
      },
    });
  }

  /**
   * EN: Find verification by user and type
   * VI: Tìm xác thực theo user và loại
   */
  async findByUserAndType(userId: string, type: VerificationType): Promise<IdentityVerification | null> {
    return this.prisma.identityVerification.findFirst({
      where: {
        userId,
        type,
        status: {
          in: [VerificationStatus.PENDING, VerificationStatus.VERIFIED],
        },
      },
      orderBy: {
        createdAt: 'desc',
      },
      include: {
        user: {
          select: {
            id: true,
            email: true,
          },
        },
      },
    });
  }

  /**
   * EN: Create verification record
   * VI: Tạo bản ghi xác thực
   */
  async createVerification(data: {
    userId: string;
    type: VerificationType;
    status?: VerificationStatus;
    method?: string;
    token?: string;
    expiresAt?: Date;
    metadata?: any;
  }): Promise<IdentityVerification> {
    return this.prisma.identityVerification.create({
      data: {
        userId: data.userId,
        type: data.type,
        status: data.status || VerificationStatus.PENDING,
        method: data.method,
        token: data.token,
        expiresAt: data.expiresAt,
        metadata: data.metadata,
      },
      include: {
        user: {
          select: {
            id: true,
            email: true,
          },
        },
      },
    });
  }

  /**
   * EN: Update verification status
   * VI: Cập nhật trạng thái xác thực
   */
  async updateStatus(id: string, status: VerificationStatus, verifiedAt?: Date): Promise<IdentityVerification> {
    return this.prisma.identityVerification.update({
      where: { id },
      data: {
        status,
        verifiedAt: verifiedAt || (status === VerificationStatus.VERIFIED ? new Date() : null),
      },
      include: {
        user: {
          select: {
            id: true,
            email: true,
          },
        },
      },
    });
  }

  /**
   * EN: Find pending verifications for user
   * VI: Tìm các xác thực đang chờ của user
   */
  async findPendingByUser(userId: string): Promise<IdentityVerification[]> {
    return this.prisma.identityVerification.findMany({
      where: {
        userId,
        status: VerificationStatus.PENDING,
        OR: [
          { expiresAt: null },
          { expiresAt: { gte: new Date() } },
        ],
      },
      orderBy: {
        createdAt: 'desc',
      },
    });
  }

  /**
   * EN: Find verified verifications for user
   * VI: Tìm các xác thực đã xác nhận của user
   */
  async findVerifiedByUser(userId: string): Promise<IdentityVerification[]> {
    return this.prisma.identityVerification.findMany({
      where: {
        userId,
        status: VerificationStatus.VERIFIED,
      },
      orderBy: {
        verifiedAt: 'desc',
      },
    });
  }

  /**
   * EN: Expire old pending verifications
   * VI: Hết hạn các xác thực đang chờ cũ
   */
  async expireOldPending(): Promise<number> {
    const result = await this.prisma.identityVerification.updateMany({
      where: {
        status: VerificationStatus.PENDING,
        expiresAt: {
          lt: new Date(),
        },
      },
      data: {
        status: VerificationStatus.EXPIRED,
      },
    });
    return result.count;
  }
}
