import { PrismaClient, AccessReview, AccessReviewItem, ReviewStatus, ReviewType, ReviewItemStatus } from '@prisma/client';

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

/**
 * EN: Access Review repository for database operations
 * VI: Repository đánh giá truy cập cho các thao tác database
 */
export class AccessReviewRepository extends BaseRepository<AccessReview, any, any> {
  constructor(prisma?: PrismaClient) {
    super(prisma || getPrismaClient(), 'accessReview');
  }

  /**
   * EN: Find active reviews
   * VI: Tìm các đánh giá đang hoạt động
   */
  async findActive(): Promise<AccessReview[]> {
    return this.prisma.accessReview.findMany({
      where: {
        status: ReviewStatus.ACTIVE,
        startDate: { lte: new Date() },
        endDate: { gte: new Date() },
      },
      include: {
        items: {
          take: 10, // Limit for performance
        },
      },
      orderBy: {
        startDate: 'desc',
      },
    });
  }

  /**
   * EN: Find reviews by status
   * VI: Tìm các đánh giá theo trạng thái
   */
  async findByStatus(status: ReviewStatus): Promise<AccessReview[]> {
    return this.prisma.accessReview.findMany({
      where: { status },
      include: {
        items: {
          take: 10,
        },
      },
      orderBy: {
        createdAt: 'desc',
      },
    });
  }

  /**
   * EN: Find review with items
   * VI: Tìm đánh giá với các items
   */
  async findWithItems(id: string): Promise<AccessReview | null> {
    return this.prisma.accessReview.findUnique({
      where: { id },
      include: {
        items: {
          include: {
            review: false,
          },
          orderBy: {
            id: 'asc',
          },
        },
      },
    });
  }

  /**
   * EN: Create access review
   * VI: Tạo đánh giá truy cập
   */
  async createReview(data: {
    name: string;
    description?: string;
    type: ReviewType;
    startDate: Date;
    endDate: Date;
    createdBy: string;
  }): Promise<AccessReview> {
    return this.prisma.accessReview.create({
      data: {
        name: data.name,
        description: data.description,
        type: data.type,
        status: ReviewStatus.DRAFT,
        startDate: data.startDate,
        endDate: data.endDate,
        createdBy: data.createdBy,
      },
      include: {
        items: true,
      },
    });
  }

  /**
   * EN: Update review status
   * VI: Cập nhật trạng thái đánh giá
   */
  async updateStatus(id: string, status: ReviewStatus, completedAt?: Date): Promise<AccessReview> {
    return this.prisma.accessReview.update({
      where: { id },
      data: {
        status,
        completedAt: completedAt || (status === ReviewStatus.COMPLETED ? new Date() : null),
      },
      include: {
        items: {
          take: 10,
        },
      },
    });
  }

  /**
   * EN: Get review items
   * VI: Lấy các items của đánh giá
   */
  async getItems(reviewId: string): Promise<AccessReviewItem[]> {
    return this.prisma.accessReviewItem.findMany({
      where: { reviewId },
      orderBy: {
        id: 'asc',
      },
    });
  }

  /**
   * EN: Create review item
   * VI: Tạo item đánh giá
   */
  async createItem(data: {
    reviewId: string;
    userId: string;
    resource: string;
    access: any;
  }): Promise<AccessReviewItem> {
    return this.prisma.accessReviewItem.create({
      data: {
        reviewId: data.reviewId,
        userId: data.userId,
        resource: data.resource,
        access: data.access,
        status: ReviewItemStatus.PENDING,
      },
    });
  }

  /**
   * EN: Update review item status
   * VI: Cập nhật trạng thái item đánh giá
   */
  async updateItemStatus(
    itemId: string,
    status: ReviewItemStatus,
    reviewedBy: string,
    comments?: string
  ): Promise<AccessReviewItem> {
    return this.prisma.accessReviewItem.update({
      where: { id: itemId },
      data: {
        status,
        reviewedBy,
        reviewedAt: new Date(),
        comments,
      },
    });
  }

  /**
   * EN: Get review items by user
   * VI: Lấy các items đánh giá theo user
   */
  async getUserItems(userId: string, reviewId: string): Promise<AccessReviewItem[]> {
    return this.prisma.accessReviewItem.findMany({
      where: {
        userId,
        reviewId,
      },
      orderBy: {
        id: 'asc',
      },
    });
  }

  /**
   * EN: Get review statistics
   * VI: Lấy thống kê đánh giá
   */
  async getReviewStats(reviewId: string): Promise<{
    total: number;
    pending: number;
    approved: number;
    revoked: number;
    noChange: number;
  }> {
    const items = await this.prisma.accessReviewItem.findMany({
      where: { reviewId },
      select: { status: true },
    });

    return {
      total: items.length,
      pending: items.filter((i) => i.status === ReviewItemStatus.PENDING).length,
      approved: items.filter((i) => i.status === ReviewItemStatus.APPROVED).length,
      revoked: items.filter((i) => i.status === ReviewItemStatus.REVOKED).length,
      noChange: items.filter((i) => i.status === ReviewItemStatus.NO_CHANGE).length,
    };
  }

  /**
   * EN: Bulk create review items
   * VI: Tạo hàng loạt items đánh giá
   */
  async createItems(items: Array<{
    reviewId: string;
    userId: string;
    resource: string;
    access: any;
  }>): Promise<number> {
    const result = await this.prisma.accessReviewItem.createMany({
      data: items.map((item) => ({
        reviewId: item.reviewId,
        userId: item.userId,
        resource: item.resource,
        access: item.access,
        status: ReviewItemStatus.PENDING,
      })),
    });
    return result.count;
  }
}
