import {
  Prisma,
  AttendanceRegistration,
  AttendanceRegistrationStaging,
} from '@prisma/client';

export class AttendanceRegistrationLoader {
  public static determineLoadOperations(
    stagingAttendanceRegistrations: AttendanceRegistrationStaging[],
    finalAttendanceRegistrations: AttendanceRegistration[],
  ): {
    deleted: number[];
    updated: Prisma.AttendanceRegistrationCreateInput[];
    created: Prisma.AttendanceRegistrationCreateInput[];
  } {
    const deletedAttendanceRegistrations = finalAttendanceRegistrations.filter(
      (finalAttendanceRegistration) =>
        !stagingAttendanceRegistrations.find(
          (stagingAttendanceRegistration) =>
            stagingAttendanceRegistration.attendanceRegistrationId ===
            finalAttendanceRegistration.attendanceRegistrationId,
        ),
    );
    const attendanceRegistrationsToInsert =
      stagingAttendanceRegistrations.filter(
        ({ attendanceRegistrationId }) =>
          !!attendanceRegistrationId &&
          !deletedAttendanceRegistrations.find(
            (deletedAttendanceRegistration) =>
              deletedAttendanceRegistration.attendanceRegistrationId ===
              attendanceRegistrationId,
          ),
      );
    const newAttendanceRegistrations: Prisma.AttendanceRegistrationCreateInput[] =
      [];
    const updatedAttendanceRegistrations: Prisma.AttendanceRegistrationCreateInput[] =
      [];
    for (const stagingAttendanceRegistration of attendanceRegistrationsToInsert) {
      const finalAttendanceRegistration = finalAttendanceRegistrations.find(
        (finalAttendanceRegistration) =>
          finalAttendanceRegistration.attendanceRegistrationId ===
          stagingAttendanceRegistration.attendanceRegistrationId,
      );
      if (finalAttendanceRegistration) {
        updatedAttendanceRegistrations.push(
          this.attendanceRegistrationStagingToFinal(
            stagingAttendanceRegistration,
          ),
        );
      } else {
        newAttendanceRegistrations.push(
          this.attendanceRegistrationStagingToFinal(
            stagingAttendanceRegistration,
          ),
        );
      }
    }

    return {
      deleted: deletedAttendanceRegistrations.map(
        ({ attendanceRegistrationId }) => attendanceRegistrationId,
      ),
      updated: updatedAttendanceRegistrations,
      created: newAttendanceRegistrations,
    };
  }

  private static attendanceRegistrationStagingToFinal(
    attendanceregistration: AttendanceRegistrationStaging,
  ): Prisma.AttendanceRegistrationCreateInput {
    const { attendanceRegistrationId, employeeId, dateTime, event } =
      attendanceregistration;

    return {
      attendanceRegistrationId,
      employeeId,
      dateTime,
      event,
      personnelNumber: '',
    };
  }
}
