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

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

  listSeries() {
    return this.prisma.meetingSeries.findMany({
      where: {
        isActive: true,
      },
      include: {
        creator: {
          select: {
            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 } },
              },
            },
          },
        },
        meetings: {
          select: {
            id: true,
            title: true,
            startTime: true,
            endTime: true,
            status: true,
            instanceNumber: true,
            location: true,
            qrCodeOnline: true,
            qrCodeOffline: true,
          },
          orderBy: [{ startTime: 'asc' }, { instanceNumber: 'asc' }],
        },
      },
      orderBy: { createdAt: 'desc' },
    });
  }

  findSeriesById(id: string) {
    return this.prisma.meetingSeries.findUnique({
      where: { id },
    });
  }

  findSeriesWithMeetings(id: string) {
    return this.prisma.meetingSeries.findUnique({
      where: { id },
      include: {
        creator: {
          select: {
            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 } },
              },
            },
          },
        },
        meetings: {
          include: {
            attendances: {
              include: {
                user: {
                  select: {
                    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 } },
                      },
                    },
                  },
                },
              },
            },
            requiredAttendees: {
              include: {
                user: {
                  select: {
                    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 } },
                      },
                    },
                  },
                },
              },
            },
          },
          orderBy: [{ startTime: 'asc' }, { instanceNumber: 'asc' }],
        },
      },
    });
  }

  createSeries(data: Prisma.MeetingSeriesCreateInput) {
    return this.prisma.meetingSeries.create({ data });
  }

  updateSeries(id: string, data: Prisma.MeetingSeriesUpdateInput) {
    return this.prisma.meetingSeries.update({ where: { id }, data });
  }

  deleteSeries(id: string) {
    return this.prisma.meetingSeries.delete({ where: { id } });
  }

  listSeriesMeetings(id: string) {
    return this.prisma.meeting.findMany({
      where: { seriesId: id },
      orderBy: [{ startTime: 'asc' }, { instanceNumber: 'asc' }],
    });
  }

  listSeriesMeetingsWithAttendees(id: string) {
    return this.prisma.meeting.findMany({
      where: { seriesId: id },
      include: {
        requiredAttendees: {
          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 } },
                  },
                },
              },
            },
          },
        },
      },
      orderBy: [{ startTime: 'asc' }, { instanceNumber: 'asc' }],
    });
  }

  findSeriesWithMeetingsForAttendees(id: string) {
    return this.prisma.meetingSeries.findUnique({
      where: { id },
      include: {
        meetings: {
          include: {
            requiredAttendees: {
              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 } },
                      },
                    },
                  },
                },
              },
            },
          },
          orderBy: [{ startTime: 'asc' }, { instanceNumber: 'asc' }],
        },
      },
    });
  }

  listMeetingsForScheduleUpdate(seriesId: string, statuses: MeetingStatus[]) {
    return this.prisma.meeting.findMany({
      where: { seriesId, status: { in: statuses } },
      orderBy: { startTime: 'asc' },
    });
  }

  updateMeetingsForSeries(seriesId: string, data: Prisma.MeetingUpdateInput) {
    return this.prisma.meeting.updateMany({
      where: { seriesId },
      data,
    });
  }

  countSeriesAttendance(seriesId: string) {
    return this.prisma.meetingAttendance.findFirst({
      where: { meeting: { seriesId } },
    });
  }
}
