import { Injectable } from '@nestjs/common';
import { PrismaService } from '@core/database/prisma/prisma.service';
import { Prisma } from '@prisma/client';

@Injectable()
export class AttendanceRepository {
  constructor(private readonly prisma: PrismaService) {}

  findAttendanceByUserMeeting(userId: string, meetingId: string) {
    return this.prisma.meetingAttendance.findUnique({
      where: {
        userId_meetingId: {
          userId,
          meetingId,
        },
      },
    });
  }

  findAttendanceWithUser(userId: string, meetingId: string) {
    return this.prisma.meetingAttendance.findUnique({
      where: {
        userId_meetingId: {
          userId,
          meetingId,
        },
      },
      include: {
        user: {
          select: {
            id: true,
            displayName: true,
            email: true,
            departmentMemberships: {
              where: { leftAt: null },
              include: {
                department: { select: { id: true, name: true, code: true } },
                position: { select: { id: true, name: true, level: true } },
              },
            },
          },
        },
        meeting: {
          select: { id: true, title: true, startTime: true },
        },
      },
    });
  }

  createAttendance(data: Prisma.MeetingAttendanceCreateInput) {
    return this.prisma.meetingAttendance.create({
      data,
      include: {
        user: {
          select: {
            id: true,
            displayName: true,
            email: true,
            departmentMemberships: {
              where: { leftAt: null },
              include: {
                department: { select: { id: true, name: true, code: true } },
                position: { select: { id: true, name: true, level: true } },
              },
            },
          },
        },
        meeting: { select: { id: true, title: true, startTime: true } },
      },
    });
  }

  updateAttendance(id: string, data: Prisma.MeetingAttendanceUpdateInput) {
    return this.prisma.meetingAttendance.update({
      where: { id },
      data,
      include: {
        user: {
          select: {
            id: true,
            displayName: true,
            email: true,
            departmentMemberships: {
              where: { leftAt: null },
              include: {
                department: { select: { id: true, name: true, code: true } },
                position: { select: { id: true, name: true, level: true } },
              },
            },
          },
        },
        meeting: { select: { id: true, title: true, startTime: true } },
      },
    });
  }

  upsertAttendance(userId: string, meetingId: string, data: Prisma.MeetingAttendanceUpdateInput, createData: Prisma.MeetingAttendanceCreateInput) {
    return this.prisma.meetingAttendance.upsert({
      where: {
        userId_meetingId: { userId, meetingId },
      },
      update: data,
      create: createData,
      include: {
        user: {
          select: {
            id: true,
            displayName: true,
            email: true,
            departmentMemberships: {
              where: { leftAt: null },
              include: {
                department: { select: { id: true, name: true, code: true } },
                position: { select: { id: true, name: true, level: true } },
              },
            },
          },
        },
        meeting: { select: { id: true, title: true, startTime: true } },
      },
    });
  }

  listAttendancesByMeeting(meetingId: string) {
    return this.prisma.meetingAttendance.findMany({
      where: { meetingId },
      select: { userId: true },
    });
  }

  listAttendancesByMeetingWithUsers(meetingId: string) {
    return this.prisma.meetingAttendance.findMany({
      where: { meetingId },
      include: {
        user: {
          select: {
            displayName: true,
            departmentMemberships: {
              where: { leftAt: null },
              include: {
                department: { select: { id: true, name: true, code: true } },
                position: { select: { id: true, name: true, level: true } },
              },
            },
          },
        },
      },
    });
  }

  deleteAttendancesByUserMeeting(userId: string, meetingId: string) {
    return this.prisma.meetingAttendance.deleteMany({
      where: { userId, meetingId },
    });
  }

  findAttendanceByDevice(meetingId: string, deviceId: string) {
    return this.prisma.meetingAttendance.findFirst({
      where: { meetingId, deviceId },
    });
  }

  findAttendanceByDeviceOtherUser(meetingId: string, deviceId: string, userId: string) {
    return this.prisma.meetingAttendance.findFirst({
      where: { meetingId, deviceId, userId: { not: userId } },
      include: {
        user: {
          select: {
            id: true,
            displayName: true,
            email: true,
            departmentMemberships: {
              where: { leftAt: null },
              include: {
                department: { select: { id: true, name: true, code: true } },
                position: { select: { id: true, name: true, level: true } },
              },
            },
          },
        },
      },
    });
  }
}
