import { PrismaClient, AccessRequest, RequestStatus, AccessRequestApprover } from '@prisma/client';

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

/**
 * EN: Access Request repository for database operations
 * VI: Repository yêu cầu truy cập cho các thao tác database
 */
export class AccessRequestRepository extends BaseRepository<AccessRequest, any, any> {
  constructor(prisma?: PrismaClient) {
    super(prisma || getPrismaClient(), 'accessRequest');
  }

  /**
   * EN: Find requests by user
   * VI: Tìm các yêu cầu theo user
   */
  async findByUser(userId: string): Promise<AccessRequest[]> {
    return this.prisma.accessRequest.findMany({
      where: { userId },
      include: {
        user: {
          select: {
            id: true,
            email: true,
            username: true,
          },
        },
        approvers: true,
      },
      orderBy: {
        requestedAt: 'desc',
      },
    });
  }

  /**
   * EN: Find pending requests by user
   * VI: Tìm các yêu cầu đang chờ theo user
   */
  async findPendingByUser(userId: string): Promise<AccessRequest[]> {
    return this.prisma.accessRequest.findMany({
      where: {
        userId,
        status: RequestStatus.PENDING,
        OR: [
          { expiresAt: null },
          { expiresAt: { gte: new Date() } },
        ],
      },
      include: {
        user: {
          select: {
            id: true,
            email: true,
            username: true,
          },
        },
        approvers: true,
      },
      orderBy: {
        requestedAt: 'desc',
      },
    });
  }

  /**
   * EN: Find request with full details
   * VI: Tìm yêu cầu với đầy đủ chi tiết
   */
  async findWithDetails(id: string): Promise<AccessRequest | null> {
    return this.prisma.accessRequest.findUnique({
      where: { id },
      include: {
        user: {
          select: {
            id: true,
            email: true,
            username: true,
            profile: true,
          },
        },
        approvers: {
          include: {
            request: false,
          },
        },
      },
    });
  }

  /**
   * EN: Create access request
   * VI: Tạo yêu cầu truy cập
   */
  async createRequest(data: {
    userId: string;
    resource: string;
    action: string;
    reason?: string;
    expiresAt?: Date;
    metadata?: any;
  }): Promise<AccessRequest> {
    return this.prisma.accessRequest.create({
      data: {
        userId: data.userId,
        resource: data.resource,
        action: data.action,
        reason: data.reason,
        expiresAt: data.expiresAt,
        metadata: data.metadata,
        status: RequestStatus.PENDING,
      },
      include: {
        user: {
          select: {
            id: true,
            email: true,
            username: true,
          },
        },
        approvers: true,
      },
    });
  }

  /**
   * EN: Update request status
   * VI: Cập nhật trạng thái yêu cầu
   */
  async updateStatus(
    id: string,
    status: RequestStatus,
    reviewedBy: string,
    reviewedAt?: Date
  ): Promise<AccessRequest> {
    return this.prisma.accessRequest.update({
      where: { id },
      data: {
        status,
        reviewedBy,
        reviewedAt: reviewedAt || new Date(),
      },
      include: {
        user: {
          select: {
            id: true,
            email: true,
            username: true,
          },
        },
        approvers: true,
      },
    });
  }

  /**
   * EN: Add approver to request
   * VI: Thêm người phê duyệt vào yêu cầu
   */
  async addApprover(requestId: string, approverId: string): Promise<AccessRequestApprover> {
    return this.prisma.accessRequestApprover.create({
      data: {
        requestId,
        approverId,
        status: 'PENDING',
      },
    });
  }

  /**
   * EN: Find requests pending approval by approver
   * VI: Tìm các yêu cầu đang chờ phê duyệt theo người phê duyệt
   */
  async findPendingApprovals(approverId: string): Promise<AccessRequest[]> {
    return this.prisma.accessRequest.findMany({
      where: {
        status: RequestStatus.PENDING,
        approvers: {
          some: {
            approverId,
            status: 'PENDING',
          },
        },
        OR: [
          { expiresAt: null },
          { expiresAt: { gte: new Date() } },
        ],
      },
      include: {
        user: {
          select: {
            id: true,
            email: true,
            username: true,
          },
        },
        approvers: true,
      },
      orderBy: {
        requestedAt: 'asc',
      },
    });
  }

  /**
   * EN: Update approver status
   * VI: Cập nhật trạng thái người phê duyệt
   */
  async updateApproverStatus(
    requestId: string,
    approverId: string,
    status: 'APPROVED' | 'REJECTED',
    comments?: string
  ): Promise<AccessRequestApprover> {
    return this.prisma.accessRequestApprover.update({
      where: {
        requestId_approverId: {
          requestId,
          approverId,
        },
      },
      data: {
        status,
        comments,
        reviewedAt: new Date(),
      },
    });
  }

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