package com.axelor.apps.hr.service;

import com.axelor.apps.base.db.Period;
import com.axelor.apps.hr.db.Absence;
import com.axelor.apps.hr.db.DailyReport;
import com.axelor.apps.hr.db.Employee;
import com.axelor.apps.hr.db.LeaveRequest;
import com.axelor.apps.hr.db.MonthlyReport;
import com.axelor.apps.hr.db.repo.AbsenceRepository;
import com.axelor.apps.hr.db.repo.AuthorizationRepository;
import com.axelor.apps.hr.db.repo.DailyReportRepository;
import com.axelor.apps.hr.db.repo.MonthlyReportRepository;
import com.google.inject.persist.Transactional;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.util.List;
import java.util.Set;
import javax.inject.Inject;

public class MonthlyReportServiceImpl implements MonthlyReportService {

  private final MonthlyReportRepository monthlyReportRepository;
  private final DailyReportRepository dailyReportRepository;
  private final AuthorizationRepository authorizationRepository;
  private final AbsenceRepository absenceRepository;

  @Inject
  public MonthlyReportServiceImpl(
      MonthlyReportRepository monthlyReportRepository,
      DailyReportRepository dailyReportRepository,
      AuthorizationRepository authorizationRepository,
      AbsenceRepository absenceRepository) {

    this.monthlyReportRepository = monthlyReportRepository;
    this.dailyReportRepository = dailyReportRepository;
    this.authorizationRepository = authorizationRepository;
    this.absenceRepository = absenceRepository;
  }

  @Transactional
  @Override
  public void createMensuelReport(
      Employee employee,
      Period period,
      LocalDate startDate,
      LocalDate endDate,
      List<DailyReport> employeeDailyReports,
      List<Absence> employeeAbsences) {

    Boolean hasNuissance = employee.getHasNuissance();
    LocalDate firstDayOfMonth = endDate.with(TemporalAdjusters.firstDayOfMonth());
    // Perform calculations
    Integer monthlyAllowance = 0;
    Integer monthlyAllowanceRecall = 0;
    BigDecimal monthlyNightHours = BigDecimal.ZERO;
    BigDecimal monthlyExtraHours50 = BigDecimal.ZERO;
    BigDecimal monthlyExtraHours100 = BigDecimal.ZERO;
    BigDecimal excessHours50 = BigDecimal.ZERO;
    BigDecimal excessHours100 = BigDecimal.ZERO;
    BigDecimal totalSupHours = BigDecimal.ZERO;

    BigDecimal monthlyITP = BigDecimal.ZERO;
    BigDecimal totalNuissance = BigDecimal.ZERO;
    BigDecimal totalAbsence = BigDecimal.ZERO;
    BigDecimal totalWorkHours = BigDecimal.ZERO;

    BigDecimal breastfeedingAbsenceMonth = BigDecimal.ZERO;
    BigDecimal authorizedPaidAbsenceMonth = BigDecimal.ZERO;
    BigDecimal recuperationLeaveAbsenceMonth = BigDecimal.ZERO;
    BigDecimal trainingAbsenceMonth = BigDecimal.ZERO;
    BigDecimal missionAbsenceMonth = BigDecimal.ZERO;
    BigDecimal hospitalizationAbsenceMonth = BigDecimal.ZERO;
    BigDecimal sicknessAbsenceMonth = BigDecimal.ZERO;
    BigDecimal workAccidentMonth = BigDecimal.ZERO;
    BigDecimal maternityMonth = BigDecimal.ZERO;
    BigDecimal authorizedUnpaidAbsenceMonth = BigDecimal.ZERO;
    BigDecimal annualLeaveAbsenceMonth = BigDecimal.ZERO;
    BigDecimal unpaidLeaveAbsenceMonth = BigDecimal.ZERO;
    BigDecimal statutoryLeaveAbsenceMonth = BigDecimal.ZERO;
    BigDecimal resignationAbsenceMonth = BigDecimal.ZERO;
    BigDecimal contractEndAbsenceMonth = BigDecimal.ZERO;
    BigDecimal justifiedAbsenceMonth = BigDecimal.ZERO;
    BigDecimal recruitmentAbsenceMonth = BigDecimal.ZERO;
    BigDecimal suspensionAbsenceMonth = BigDecimal.ZERO;
    BigDecimal militaryServiceAbsence = BigDecimal.ZERO;
    BigDecimal irregularAbsenceMonth = BigDecimal.ZERO;

    // monthlyAllowance = monthlyAllowance + remainingDateToLastOfMonth;

    // Calculate totals for DailyReport
    for (DailyReport dailyReport : employeeDailyReports) {
      // Panier
      /*LocalDate reportDate = dailyReport.getReportDate();
      Integer panier = dailyReport.getPanier();
      if (reportDate.isAfter(firstDayOfMonth) && panier == 1) {
        monthlyAllowance = monthlyAllowance + 1;
      }*/

      monthlyAllowance = monthlyAllowance + dailyReport.getAllowance();
      ;
      monthlyAllowanceRecall = monthlyAllowanceRecall + dailyReport.getAllowanceRecall();
      monthlyNightHours = monthlyNightHours.add(dailyReport.getNightHours());
      totalWorkHours = totalWorkHours.add(dailyReport.getWorkHours());

      BigDecimal heureSup50 =
          dailyReport.getExtraHours50() != null ? dailyReport.getExtraHours50() : BigDecimal.ZERO;
      BigDecimal heureSup100 =
          dailyReport.getExtraHours100() != null ? dailyReport.getExtraHours100() : BigDecimal.ZERO;
      BigDecimal itp = dailyReport.getItp() != null ? dailyReport.getItp() : BigDecimal.ZERO;
      BigDecimal nuissance =
          dailyReport.getNuissance() != null ? dailyReport.getNuissance() : BigDecimal.ZERO;

      BigDecimal supHours50ToDeduce =
          dailyReport.getSupHours50ToDeduce() != null
              ? dailyReport.getSupHours50ToDeduce()
              : BigDecimal.ZERO;
      BigDecimal supHours100ToDeduce =
          dailyReport.getSupHours100ToDeduce() != null
              ? dailyReport.getSupHours100ToDeduce()
              : BigDecimal.ZERO;
      BigDecimal itpToDeduce =
          dailyReport.getItpToDeduce() != null ? dailyReport.getItpToDeduce() : BigDecimal.ZERO;
      BigDecimal nuissanceToDeduce =
          dailyReport.getNuissanceToDeduce() != null
              ? dailyReport.getNuissanceToDeduce()
              : BigDecimal.ZERO;

      if (dailyReport.getDeduceSupHours50() && heureSup50.compareTo(supHours50ToDeduce) > 0) {
        heureSup50 = heureSup50.subtract(supHours50ToDeduce);
      }

      if (dailyReport.getDeduceSupHours100() && heureSup100.compareTo(supHours100ToDeduce) > 0) {
        heureSup100 = heureSup100.subtract(supHours100ToDeduce);
      }

      if (dailyReport.getDeduceItp() && itp.compareTo(itpToDeduce) > 0) {
        itp = itp.subtract(itpToDeduce);
      }

      if (dailyReport.getDeduceNuissance() && nuissance.compareTo(nuissanceToDeduce) > 0) {
        nuissance = nuissance.subtract(nuissanceToDeduce);
      }

      monthlyITP = monthlyITP.add(itp);
      totalNuissance = totalNuissance.add(nuissance);

      // Sup Hours
      if (dailyReport.getIsValidSupHours()) {

        // Handle HeureSup50
        if (heureSup50 != null) {
          if (totalSupHours.add(heureSup50).compareTo(new BigDecimal(32)) <= 0) {
            // If the total hours are still less than or equal to 32 after adding new hours
            monthlyExtraHours50 = monthlyExtraHours50.add(heureSup50);
            totalSupHours = totalSupHours.add(heureSup50);
          } else if (totalSupHours.compareTo(new BigDecimal(32)) < 0) {
            // If totalSupHours is less than 32, but adding heureSup50 exceeds 32
            BigDecimal remainingHours = new BigDecimal(32).subtract(totalSupHours);
            monthlyExtraHours50 = monthlyExtraHours50.add(remainingHours);
            totalSupHours = totalSupHours.add(remainingHours);

            // Add the excess to excessHours50
            excessHours50 = excessHours50.add(heureSup50.subtract(remainingHours));
          } else {
            // If totalSupHours already exceeds 32, all new hours go to excess
            excessHours50 = excessHours50.add(heureSup50);
          }
        }
        // Handle HeureSup100
        if (heureSup100 != null) {
          if (totalSupHours.add(heureSup100).compareTo(new BigDecimal(32)) <= 0) {
            // If the total hours are still less than or equal to 32 after adding new hours
            monthlyExtraHours100 = monthlyExtraHours100.add(heureSup100);
            totalSupHours = totalSupHours.add(heureSup100);
          } else if (totalSupHours.compareTo(new BigDecimal(32)) < 0) {
            // If totalSupHours is less than 32, but adding heureSup100 exceeds 32
            BigDecimal remainingHours = new BigDecimal(32).subtract(totalSupHours);
            monthlyExtraHours100 = monthlyExtraHours100.add(remainingHours);
            totalSupHours = totalSupHours.add(remainingHours);

            // Add the excess to excessHours100
            excessHours100 = excessHours100.add(heureSup100.subtract(remainingHours));
          } else {
            // If totalSupHours already exceeds 32, all new hours go to excess
            excessHours100 = excessHours100.add(heureSup100);
          }
        }
      }

      Boolean isAuthorizedAbsence = dailyReport.getIsAuthorizedAbsence();
      Boolean isAuthorizedLateArrival = dailyReport.getIsAuthorizedLateArrival();
      Boolean isAuthorizedEarlyDeparture = dailyReport.getIsAuthorizedEarlyDeparture();
      LeaveRequest leaveRequest = dailyReport.getLeaveRequest();
      Set<Absence> absences = dailyReport.getAbsenceSet();

      if (dailyReport.getAbsenceHours() != null
          && dailyReport.getAbsenceHours().compareTo(BigDecimal.ZERO) > 0) {
        if (isAuthorizedAbsence == false
            && isAuthorizedLateArrival == false
            && isAuthorizedEarlyDeparture == false
            && leaveRequest == null
            && absences == null) {
          irregularAbsenceMonth = irregularAbsenceMonth.add(dailyReport.getAbsenceHours());
        } else if (isAuthorizedAbsence) {
          justifiedAbsenceMonth = justifiedAbsenceMonth.add(dailyReport.getAbsenceHours());
        } else if (isAuthorizedLateArrival) {
          justifiedAbsenceMonth = justifiedAbsenceMonth.add(dailyReport.getLateArrival());
        } else if (isAuthorizedEarlyDeparture) {
          justifiedAbsenceMonth = justifiedAbsenceMonth.add(dailyReport.getEarlyDeparture());
        } else if (leaveRequest != null) {
          recuperationLeaveAbsenceMonth =
              recuperationLeaveAbsenceMonth.add(dailyReport.getAbsenceHours());
        } else if (absences != null) {
          for (Absence absence : absences) {
            totalAbsence = dailyReport.getAbsenceHours();
            switch (absence.getAbsenceType()) {
              case 0:
                breastfeedingAbsenceMonth = breastfeedingAbsenceMonth.add(totalAbsence);
                break;
              case 1:
                recuperationLeaveAbsenceMonth = recuperationLeaveAbsenceMonth.add(totalAbsence);
                break;
              case 2:
                breastfeedingAbsenceMonth = breastfeedingAbsenceMonth.add(totalAbsence);
                break;
              case 3:
                trainingAbsenceMonth = trainingAbsenceMonth.add(totalAbsence);
                break;
              case 4:
                missionAbsenceMonth = missionAbsenceMonth.add(totalAbsence);
                break;
              case 5:
                hospitalizationAbsenceMonth = hospitalizationAbsenceMonth.add(totalAbsence);
                break;
              case 6:
                sicknessAbsenceMonth = sicknessAbsenceMonth.add(totalAbsence);
                break;
              case 7:
                workAccidentMonth = workAccidentMonth.add(totalAbsence);
                break;
              case 8:
                maternityMonth = maternityMonth.add(totalAbsence);
                break;
              case 9:
                authorizedUnpaidAbsenceMonth = authorizedUnpaidAbsenceMonth.add(totalAbsence);
                break;
              case 10:
                annualLeaveAbsenceMonth = annualLeaveAbsenceMonth.add(totalAbsence);
                break;
              case 11:
                unpaidLeaveAbsenceMonth = unpaidLeaveAbsenceMonth.add(totalAbsence);
                break;
              case 12:
                statutoryLeaveAbsenceMonth = statutoryLeaveAbsenceMonth.add(totalAbsence);
                break;
              case 13:
                resignationAbsenceMonth = resignationAbsenceMonth.add(totalAbsence);
                break;
              case 14:
                contractEndAbsenceMonth = contractEndAbsenceMonth.add(totalAbsence);
                break;
              case 15:
                justifiedAbsenceMonth = justifiedAbsenceMonth.add(totalAbsence);
                break;
              case 16:
                recruitmentAbsenceMonth = recruitmentAbsenceMonth.add(totalAbsence);
                break;
              case 17:
                suspensionAbsenceMonth = suspensionAbsenceMonth.add(totalAbsence);
                break;
              case 18:
                militaryServiceAbsence = militaryServiceAbsence.add(totalAbsence);
                break;
              case 19:
                if (dailyReport.getIsAuthorizedAbsence()) {
                  justifiedAbsenceMonth = justifiedAbsenceMonth.add(totalAbsence);
                } else {
                  irregularAbsenceMonth = irregularAbsenceMonth.add(totalAbsence);
                }
                break;
              case 20:
                if (dailyReport.getIsAuthorizedLateArrival()) {
                  justifiedAbsenceMonth = justifiedAbsenceMonth.add(dailyReport.getLateArrival());
                } else {
                  irregularAbsenceMonth = irregularAbsenceMonth.add(dailyReport.getLateArrival());
                }
                break;
              case 21:
                if (dailyReport.getIsAuthorizedEarlyDeparture()) {
                  justifiedAbsenceMonth =
                      justifiedAbsenceMonth.add(dailyReport.getEarlyDeparture());
                } else {
                  irregularAbsenceMonth =
                      irregularAbsenceMonth.add(dailyReport.getEarlyDeparture());
                }
                break;
              default:
                // Handle default case
                break;
            }
          }
        }
      }
    }

    // Update or create MonthlyReport instance with calculated values
    MonthlyReport monthlyReport = new MonthlyReport();
    monthlyReport.setPeriod(period);
    monthlyReport.setEmployee(employee);
    monthlyReport.setMonthlyAllowance(monthlyAllowance);
    monthlyReport.setMonthlyAllowanceRecall(monthlyAllowanceRecall);
    monthlyReport.setMonthlyNightHours(monthlyNightHours);
    monthlyReport.setMonthlyExtraHours50(monthlyExtraHours50);
    monthlyReport.setMonthlyExtraHours100(monthlyExtraHours100);
    monthlyReport.setExcessHours50(excessHours50);
    monthlyReport.setExcessHours100(excessHours100);

    monthlyReport.setMonthlyITP(monthlyITP);
    monthlyReport.setTotalNuissance(totalNuissance);
    monthlyReport.setTotalWorkHours(totalWorkHours);

    // Set total absence values for each specific type
    monthlyReport.setBreastfeedingAbsenceMonth(breastfeedingAbsenceMonth);
    monthlyReport.setAuthorizedPaidAbsenceMonth(authorizedPaidAbsenceMonth);
    monthlyReport.setAuthorizedUnpaidAbsenceMonth(authorizedUnpaidAbsenceMonth);
    monthlyReport.setAnnualLeaveAbsenceMonth(annualLeaveAbsenceMonth);
    monthlyReport.setRecuperationLeaveAbsenceMonth(recuperationLeaveAbsenceMonth);
    monthlyReport.setUnpaidLeaveAbsenceMonth(unpaidLeaveAbsenceMonth);
    monthlyReport.setStatutoryLeaveAbsenceMonth(statutoryLeaveAbsenceMonth);
    monthlyReport.setResignationAbsenceMonth(resignationAbsenceMonth);
    monthlyReport.setContractEndAbsenceMonth(contractEndAbsenceMonth);
    monthlyReport.setTrainingAbsenceMonth(trainingAbsenceMonth);
    monthlyReport.setHospitalizationAbsenceMonth(hospitalizationAbsenceMonth);
    monthlyReport.setMissionAbsenceMonth(missionAbsenceMonth);
    monthlyReport.setSicknessAbsenceMonth(sicknessAbsenceMonth);
    monthlyReport.setWorkAccidentMonth(workAccidentMonth);
    monthlyReport.setMaternityMonth(maternityMonth);
    monthlyReport.setJustifiedAbsenceMonth(justifiedAbsenceMonth);
    monthlyReport.setRecruitmentAbsenceMonth(recruitmentAbsenceMonth);
    monthlyReport.setSuspensionAbsenceMonth(suspensionAbsenceMonth);
    monthlyReport.setMilitaryServiceAbsence(militaryServiceAbsence);
    monthlyReport.setIrregularAbsenceMonth(irregularAbsenceMonth);

    // Save the MonthlyReport instance
    monthlyReportRepository.save(monthlyReport);
  }

  public void updateMensuelReport(
      MonthlyReport monthlyReport,
      Employee employee,
      Period period,
      LocalDate startDate,
      LocalDate endDate,
      List<DailyReport> employeeDailyReports,
      List<Absence> employeeAbsences) {

    Boolean hasNuissance = employee.getHasNuissance();
    LocalDate firstDayOfMonth = endDate.with(TemporalAdjusters.firstDayOfMonth());
    // Perform calculations
    Integer monthlyAllowance = 0;
    Integer monthlyAllowanceRecall = 0;
    BigDecimal monthlyNightHours = BigDecimal.ZERO;
    BigDecimal monthlyExtraHours50 = BigDecimal.ZERO;
    BigDecimal monthlyExtraHours100 = BigDecimal.ZERO;
    BigDecimal excessHours50 = BigDecimal.ZERO;
    BigDecimal excessHours100 = BigDecimal.ZERO;
    BigDecimal totalSupHours = BigDecimal.ZERO;

    BigDecimal monthlyITP = BigDecimal.ZERO;
    BigDecimal totalNuissance = BigDecimal.ZERO;
    BigDecimal totalAbsence = BigDecimal.ZERO;
    BigDecimal totalWorkHours = BigDecimal.ZERO;

    BigDecimal breastfeedingAbsenceMonth = BigDecimal.ZERO;
    BigDecimal authorizedPaidAbsenceMonth = BigDecimal.ZERO;
    BigDecimal recuperationLeaveAbsenceMonth = BigDecimal.ZERO;
    BigDecimal trainingAbsenceMonth = BigDecimal.ZERO;
    BigDecimal missionAbsenceMonth = BigDecimal.ZERO;
    BigDecimal hospitalizationAbsenceMonth = BigDecimal.ZERO;
    BigDecimal sicknessAbsenceMonth = BigDecimal.ZERO;
    BigDecimal workAccidentMonth = BigDecimal.ZERO;
    BigDecimal maternityMonth = BigDecimal.ZERO;
    BigDecimal authorizedUnpaidAbsenceMonth = BigDecimal.ZERO;
    BigDecimal annualLeaveAbsenceMonth = BigDecimal.ZERO;
    BigDecimal unpaidLeaveAbsenceMonth = BigDecimal.ZERO;
    BigDecimal statutoryLeaveAbsenceMonth = BigDecimal.ZERO;
    BigDecimal resignationAbsenceMonth = BigDecimal.ZERO;
    BigDecimal contractEndAbsenceMonth = BigDecimal.ZERO;
    BigDecimal justifiedAbsenceMonth = BigDecimal.ZERO;
    BigDecimal recruitmentAbsenceMonth = BigDecimal.ZERO;
    BigDecimal suspensionAbsenceMonth = BigDecimal.ZERO;
    BigDecimal militaryServiceAbsence = BigDecimal.ZERO;
    BigDecimal irregularAbsenceMonth = BigDecimal.ZERO;

    // monthlyAllowance = monthlyAllowance + remainingDateToLastOfMonth;

    // Calculate totals for DailyReport
    for (DailyReport dailyReport : employeeDailyReports) {
      // Panier
      /*LocalDate reportDate = dailyReport.getReportDate();
      Integer panier = dailyReport.getPanier();
      if (reportDate.isAfter(firstDayOfMonth) && panier == 1) {
        monthlyAllowance = monthlyAllowance + 1;
      }*/

      monthlyAllowance = monthlyAllowance + dailyReport.getAllowance();
      ;
      monthlyAllowanceRecall = monthlyAllowanceRecall + dailyReport.getAllowanceRecall();
      monthlyNightHours = monthlyNightHours.add(dailyReport.getNightHours());
      totalWorkHours = totalWorkHours.add(dailyReport.getWorkHours());

      BigDecimal heureSup50 =
          dailyReport.getExtraHours50() != null ? dailyReport.getExtraHours50() : BigDecimal.ZERO;
      BigDecimal heureSup100 =
          dailyReport.getExtraHours100() != null ? dailyReport.getExtraHours100() : BigDecimal.ZERO;
      BigDecimal itp = dailyReport.getItp() != null ? dailyReport.getItp() : BigDecimal.ZERO;
      BigDecimal nuissance =
          dailyReport.getNuissance() != null ? dailyReport.getNuissance() : BigDecimal.ZERO;

      BigDecimal supHours50ToDeduce =
          dailyReport.getSupHours50ToDeduce() != null
              ? dailyReport.getSupHours50ToDeduce()
              : BigDecimal.ZERO;
      BigDecimal supHours100ToDeduce =
          dailyReport.getSupHours100ToDeduce() != null
              ? dailyReport.getSupHours100ToDeduce()
              : BigDecimal.ZERO;
      BigDecimal itpToDeduce =
          dailyReport.getItpToDeduce() != null ? dailyReport.getItpToDeduce() : BigDecimal.ZERO;
      BigDecimal nuissanceToDeduce =
          dailyReport.getNuissanceToDeduce() != null
              ? dailyReport.getNuissanceToDeduce()
              : BigDecimal.ZERO;

      if (dailyReport.getDeduceSupHours50() && heureSup50.compareTo(supHours50ToDeduce) > 0) {
        heureSup50 = heureSup50.subtract(supHours50ToDeduce);
      }

      if (dailyReport.getDeduceSupHours100() && heureSup100.compareTo(supHours100ToDeduce) > 0) {
        heureSup100 = heureSup100.subtract(supHours100ToDeduce);
      }

      if (dailyReport.getDeduceItp() && itp.compareTo(itpToDeduce) > 0) {
        itp = itp.subtract(itpToDeduce);
      }

      if (dailyReport.getDeduceNuissance() && nuissance.compareTo(nuissanceToDeduce) > 0) {
        nuissance = nuissance.subtract(nuissanceToDeduce);
      }

      monthlyITP = monthlyITP.add(itp);
      totalNuissance = totalNuissance.add(nuissance);

      // Sup Hours
      if (dailyReport.getIsValidSupHours()) {

        // Handle HeureSup50
        if (heureSup50 != null) {
          if (totalSupHours.add(heureSup50).compareTo(new BigDecimal(32)) <= 0) {
            // If the total hours are still less than or equal to 32 after adding new hours
            monthlyExtraHours50 = monthlyExtraHours50.add(heureSup50);
            totalSupHours = totalSupHours.add(heureSup50);
          } else if (totalSupHours.compareTo(new BigDecimal(32)) < 0) {
            // If totalSupHours is less than 32, but adding heureSup50 exceeds 32
            BigDecimal remainingHours = new BigDecimal(32).subtract(totalSupHours);
            monthlyExtraHours50 = monthlyExtraHours50.add(remainingHours);
            totalSupHours = totalSupHours.add(remainingHours);

            // Add the excess to excessHours50
            excessHours50 = excessHours50.add(heureSup50.subtract(remainingHours));
          } else {
            // If totalSupHours already exceeds 32, all new hours go to excess
            excessHours50 = excessHours50.add(heureSup50);
          }
        }
        // Handle HeureSup100
        if (heureSup100 != null) {
          if (totalSupHours.add(heureSup100).compareTo(new BigDecimal(32)) <= 0) {
            // If the total hours are still less than or equal to 32 after adding new hours
            monthlyExtraHours100 = monthlyExtraHours100.add(heureSup100);
            totalSupHours = totalSupHours.add(heureSup100);
          } else if (totalSupHours.compareTo(new BigDecimal(32)) < 0) {
            // If totalSupHours is less than 32, but adding heureSup100 exceeds 32
            BigDecimal remainingHours = new BigDecimal(32).subtract(totalSupHours);
            monthlyExtraHours100 = monthlyExtraHours100.add(remainingHours);
            totalSupHours = totalSupHours.add(remainingHours);

            // Add the excess to excessHours100
            excessHours100 = excessHours100.add(heureSup100.subtract(remainingHours));
          } else {
            // If totalSupHours already exceeds 32, all new hours go to excess
            excessHours100 = excessHours100.add(heureSup100);
          }
        }
      }

      Boolean isAuthorizedAbsence = dailyReport.getIsAuthorizedAbsence();
      Boolean isAuthorizedLateArrival = dailyReport.getIsAuthorizedLateArrival();
      Boolean isAuthorizedEarlyDeparture = dailyReport.getIsAuthorizedEarlyDeparture();
      LeaveRequest leaveRequest = dailyReport.getLeaveRequest();
      Set<Absence> absences = dailyReport.getAbsenceSet();

      if (dailyReport.getAbsenceHours() != null
          && dailyReport.getAbsenceHours().compareTo(BigDecimal.ZERO) > 0) {
        if (isAuthorizedAbsence == false
            && isAuthorizedLateArrival == false
            && isAuthorizedEarlyDeparture == false
            && leaveRequest == null
            && absences == null) {
          irregularAbsenceMonth = irregularAbsenceMonth.add(dailyReport.getAbsenceHours());
        } else if (isAuthorizedAbsence) {
          justifiedAbsenceMonth = justifiedAbsenceMonth.add(dailyReport.getAbsenceHours());
        } else if (isAuthorizedLateArrival) {
          justifiedAbsenceMonth = justifiedAbsenceMonth.add(dailyReport.getLateArrival());
        } else if (isAuthorizedEarlyDeparture) {
          justifiedAbsenceMonth = justifiedAbsenceMonth.add(dailyReport.getEarlyDeparture());
        } else if (leaveRequest != null) {
          recuperationLeaveAbsenceMonth =
              recuperationLeaveAbsenceMonth.add(dailyReport.getAbsenceHours());
        } else if (absences != null) {
          for (Absence absence : absences) {
            totalAbsence = dailyReport.getAbsenceHours();
            switch (absence.getAbsenceType()) {
              case 0:
                breastfeedingAbsenceMonth = breastfeedingAbsenceMonth.add(totalAbsence);
                break;
              case 1:
                recuperationLeaveAbsenceMonth = recuperationLeaveAbsenceMonth.add(totalAbsence);
                break;
              case 2:
                breastfeedingAbsenceMonth = breastfeedingAbsenceMonth.add(totalAbsence);
                break;
              case 3:
                trainingAbsenceMonth = trainingAbsenceMonth.add(totalAbsence);
                break;
              case 4:
                missionAbsenceMonth = missionAbsenceMonth.add(totalAbsence);
                break;
              case 5:
                hospitalizationAbsenceMonth = hospitalizationAbsenceMonth.add(totalAbsence);
                break;
              case 6:
                sicknessAbsenceMonth = sicknessAbsenceMonth.add(totalAbsence);
                break;
              case 7:
                workAccidentMonth = workAccidentMonth.add(totalAbsence);
                break;
              case 8:
                maternityMonth = maternityMonth.add(totalAbsence);
                break;
              case 9:
                authorizedUnpaidAbsenceMonth = authorizedUnpaidAbsenceMonth.add(totalAbsence);
                break;
              case 10:
                annualLeaveAbsenceMonth = annualLeaveAbsenceMonth.add(totalAbsence);
                break;
              case 11:
                unpaidLeaveAbsenceMonth = unpaidLeaveAbsenceMonth.add(totalAbsence);
                break;
              case 12:
                statutoryLeaveAbsenceMonth = statutoryLeaveAbsenceMonth.add(totalAbsence);
                break;
              case 13:
                resignationAbsenceMonth = resignationAbsenceMonth.add(totalAbsence);
                break;
              case 14:
                contractEndAbsenceMonth = contractEndAbsenceMonth.add(totalAbsence);
                break;
              case 15:
                justifiedAbsenceMonth = justifiedAbsenceMonth.add(totalAbsence);
                break;
              case 16:
                recruitmentAbsenceMonth = recruitmentAbsenceMonth.add(totalAbsence);
                break;
              case 17:
                suspensionAbsenceMonth = suspensionAbsenceMonth.add(totalAbsence);
                break;
              case 18:
                militaryServiceAbsence = militaryServiceAbsence.add(totalAbsence);
                break;
              case 19:
                if (dailyReport.getIsAuthorizedAbsence()) {
                  justifiedAbsenceMonth = justifiedAbsenceMonth.add(totalAbsence);
                } else {
                  irregularAbsenceMonth = irregularAbsenceMonth.add(totalAbsence);
                }
                break;
              case 20:
                if (dailyReport.getIsAuthorizedLateArrival()) {
                  justifiedAbsenceMonth = justifiedAbsenceMonth.add(dailyReport.getLateArrival());
                } else {
                  irregularAbsenceMonth = irregularAbsenceMonth.add(dailyReport.getLateArrival());
                }
                break;
              case 21:
                if (dailyReport.getIsAuthorizedEarlyDeparture()) {
                  justifiedAbsenceMonth =
                      justifiedAbsenceMonth.add(dailyReport.getEarlyDeparture());
                } else {
                  irregularAbsenceMonth =
                      irregularAbsenceMonth.add(dailyReport.getEarlyDeparture());
                }
                break;
              default:
                // Handle default case
                break;
            }
          }
        }
      }
    }

    // Update or create MonthlyReport instance with calculated values
    monthlyReport.setPeriod(period);
    monthlyReport.setEmployee(employee);
    monthlyReport.setMonthlyAllowance(monthlyAllowance);
    monthlyReport.setMonthlyAllowanceRecall(monthlyAllowanceRecall);
    monthlyReport.setMonthlyNightHours(monthlyNightHours);
    monthlyReport.setMonthlyExtraHours50(monthlyExtraHours50);
    monthlyReport.setMonthlyExtraHours100(monthlyExtraHours100);
    monthlyReport.setExcessHours50(excessHours50);
    monthlyReport.setExcessHours100(excessHours100);

    monthlyReport.setMonthlyITP(monthlyITP);
    monthlyReport.setTotalNuissance(totalNuissance);
    monthlyReport.setTotalWorkHours(totalWorkHours);

    // Set total absence values for each specific type
    monthlyReport.setBreastfeedingAbsenceMonth(breastfeedingAbsenceMonth);
    monthlyReport.setAuthorizedPaidAbsenceMonth(authorizedPaidAbsenceMonth);
    monthlyReport.setAuthorizedUnpaidAbsenceMonth(authorizedUnpaidAbsenceMonth);
    monthlyReport.setAnnualLeaveAbsenceMonth(annualLeaveAbsenceMonth);
    monthlyReport.setRecuperationLeaveAbsenceMonth(recuperationLeaveAbsenceMonth);
    monthlyReport.setUnpaidLeaveAbsenceMonth(unpaidLeaveAbsenceMonth);
    monthlyReport.setStatutoryLeaveAbsenceMonth(statutoryLeaveAbsenceMonth);
    monthlyReport.setResignationAbsenceMonth(resignationAbsenceMonth);
    monthlyReport.setContractEndAbsenceMonth(contractEndAbsenceMonth);
    monthlyReport.setTrainingAbsenceMonth(trainingAbsenceMonth);
    monthlyReport.setHospitalizationAbsenceMonth(hospitalizationAbsenceMonth);
    monthlyReport.setMissionAbsenceMonth(missionAbsenceMonth);
    monthlyReport.setSicknessAbsenceMonth(sicknessAbsenceMonth);
    monthlyReport.setWorkAccidentMonth(workAccidentMonth);
    monthlyReport.setMaternityMonth(maternityMonth);
    monthlyReport.setJustifiedAbsenceMonth(justifiedAbsenceMonth);
    monthlyReport.setRecruitmentAbsenceMonth(recruitmentAbsenceMonth);
    monthlyReport.setSuspensionAbsenceMonth(suspensionAbsenceMonth);
    monthlyReport.setMilitaryServiceAbsence(militaryServiceAbsence);
    monthlyReport.setIrregularAbsenceMonth(irregularAbsenceMonth);

    // Save the MonthlyReport instance
    monthlyReportRepository.save(monthlyReport);
  }

  /*
  @Transactional
  public void calculePrimeAssiduite(MonthlyReport monthlyReport) {
    BigDecimal primeAssiduite = BigDecimal.ZERO;
    BigDecimal excessHours50 = MonthlyReport.getExcessHours50();
    BigDecimal excessHours100 = MonthlyReport.getExcessHours100();

    // Calculate primeAssiduite using the provided formula
    BigDecimal salaireBase = monthlyReport.getEmployee().getSalaireBase();
    BigDecimal supHours50Bonus = excessHours50.multiply(salaireBase
                                                        .multiply(new BigDecimal(1.5).setScale(2, RoundingMode.HALF_UP))
                                                        .divide(new BigDecimal(176), 2, RoundingMode.HALF_UP)
                                                        .setScale(2, RoundingMode.HALF_UP))
                                                        .setScale(2, RoundingMode.HALF_UP);

    BigDecimal supHours100Bonus = excessHours100.multiply(salaireBase
                                                          .multiply(new BigDecimal(2).setScale(2, RoundingMode.HALF_UP))
                                                          .divide(new BigDecimal(176), 2, RoundingMode.HALF_UP)
                                                          .setScale(2, RoundingMode.HALF_UP))
                                                          .setScale(2, RoundingMode.HALF_UP);

    primeAssiduite = supHours50Bonus.add(supHours100Bonus);

    monthlyReport.setPrimeAssiduite(primeAssiduite.setScale(2, RoundingMode.HALF_UP));
    // Save the MonthlyReport instance
    monthlyReportRepository.save(monthlyReport);
  }
  */
}
