import { PrismaClient, Role, Permission } from '@prisma/client';

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

/**
 * EN: Role repository for database operations
 * VI: Repository role cho các thao tác database
 */
export class RoleRepository extends BaseRepository<Role, any, any> {
  constructor(prisma: PrismaClient) {
    super(prisma, 'role');
  }

  /**
   * EN: Find role by name
   * VI: Tìm role theo tên
   */
  async findByName(name: string): Promise<Role | null> {
    return this.prisma.role.findUnique({
      where: { name },
      include: {
        permissions: {
          include: { permission: true },
        },
      },
    });
  }

  /**
   * EN: Find role with permissions
   * VI: Tìm role với permissions
   */
  async findWithPermissions(roleId: string): Promise<Role | null> {
    return this.prisma.role.findUnique({
      where: { id: roleId },
      include: {
        permissions: {
          include: { permission: true },
        },
      },
    });
  }

  /**
   * EN: Get all roles with permissions
   * VI: Lấy tất cả roles với permissions
   */
  async findAllWithPermissions(): Promise<Role[]> {
    return this.prisma.role.findMany({
      include: {
        permissions: {
          include: { permission: true },
        },
      },
      orderBy: { createdAt: 'asc' },
    });
  }
}

/**
 * EN: Permission repository
 * VI: Repository permission
 */
export class PermissionRepository extends BaseRepository<Permission, any, any> {
  constructor(prisma: PrismaClient) {
    super(prisma, 'permission');
  }

  /**
   * EN: Find permission by resource, action, and scope
   * VI: Tìm permission theo resource, action và scope
   */
  async findByResourceAction(
    resource: string,
    action: string,
    scope?: string
  ): Promise<Permission | null> {
    // EN: Handle nullable scope in unique constraint
    // VI: Xử lý scope nullable trong unique constraint
    return this.prisma.permission.findUnique({
      where: scope !== undefined
        ? {
            resource_action_scope: {
              resource,
              action,
              scope,
            },
          }
        : ({
            resource_action_scope: {
              resource,
              action,
              scope: null,
            },
          } as any),
    });
  }

  /**
   * EN: Find permissions by resource
   * VI: Tìm permissions theo resource
   */
  async findByResource(resource: string): Promise<Permission[]> {
    return this.prisma.permission.findMany({
      where: { resource },
      orderBy: { action: 'asc' },
    });
  }
}
