import { PrismaClient, Group, GroupMember } from '@prisma/client';

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

/**
 * EN: Group repository for database operations
 * VI: Repository nhóm cho các thao tác database
 */
export class GroupRepository extends BaseRepository<Group, any, any> {
  constructor(prisma?: PrismaClient) {
    super(prisma || getPrismaClient(), 'group');
  }

  /**
   * EN: Find groups by organization
   * VI: Tìm các nhóm theo tổ chức
   */
  async findByOrganization(organizationId: string): Promise<Group[]> {
    return this.prisma.group.findMany({
      where: { organizationId },
      include: {
        organization: true,
        members: {
          include: {
            user: {
              select: {
                id: true,
                email: true,
                username: true,
              },
            },
          },
        },
        permissions: {
          include: {
            permission: true,
          },
        },
      },
    });
  }

  /**
   * EN: Find user groups
   * VI: Tìm các nhóm của user
   */
  async findUserGroups(userId: string): Promise<Group[]> {
    return this.prisma.group.findMany({
      where: {
        members: {
          some: {
            userId,
            OR: [
              { expiresAt: null },
              { expiresAt: { gte: new Date() } },
            ],
          },
        },
      },
      include: {
        organization: true,
        permissions: {
          include: {
            permission: true,
          },
        },
      },
    });
  }

  /**
   * EN: Add member to group
   * VI: Thêm thành viên vào nhóm
   */
  async addMember(groupId: string, userId: string, role: string = 'member', expiresAt?: Date): Promise<GroupMember> {
    return this.prisma.groupMember.upsert({
      where: {
        userId_groupId: {
          userId,
          groupId,
        },
      },
      update: {
        role,
        expiresAt,
      },
      create: {
        groupId,
        userId,
        role,
        expiresAt,
      },
    });
  }

  /**
   * EN: Remove member from group
   * VI: Xóa thành viên khỏi nhóm
   */
  async removeMember(groupId: string, userId: string): Promise<boolean> {
    await this.prisma.groupMember.delete({
      where: {
        userId_groupId: {
          userId,
          groupId,
        },
      },
    });
    return true;
  }

  /**
   * EN: Get group members
   * VI: Lấy các thành viên của nhóm
   */
  async getMembers(groupId: string): Promise<GroupMember[]> {
    return this.prisma.groupMember.findMany({
      where: { groupId },
      include: {
        user: {
          select: {
            id: true,
            email: true,
            username: true,
            isActive: true,
          },
        },
      },
      orderBy: {
        joinedAt: 'desc',
      },
    });
  }

  /**
   * EN: Get member count
   * VI: Lấy số lượng thành viên
   */
  async getMemberCount(groupId: string): Promise<number> {
    return this.prisma.groupMember.count({
      where: {
        groupId,
        OR: [
          { expiresAt: null },
          { expiresAt: { gte: new Date() } },
        ],
      },
    });
  }

  /**
   * EN: Assign permission to group
   * VI: Gán quyền cho nhóm
   */
  async assignPermission(groupId: string, permissionId: string): Promise<void> {
    await this.prisma.groupPermission.upsert({
      where: {
        groupId_permissionId: {
          groupId,
          permissionId,
        },
      },
      update: {},
      create: {
        groupId,
        permissionId,
      },
    });
  }

  /**
   * EN: Revoke permission from group
   * VI: Thu hồi quyền khỏi nhóm
   */
  async revokePermission(groupId: string, permissionId: string): Promise<void> {
    await this.prisma.groupPermission.delete({
      where: {
        groupId_permissionId: {
          groupId,
          permissionId,
        },
      },
    });
  }
}
