package org.mte.numecoeval.calculs.infrastructure.service.sync.calculs;

import lombok.AllArgsConstructor;
import org.mte.numecoeval.calculs.domain.model.CalculSizes;
import org.mte.numecoeval.calculs.infrastructure.repository.EquipementPhysiqueRepository;
import org.mte.numecoeval.calculs.infrastructure.repository.MessagerieRepository;
import org.mte.numecoeval.calculs.infrastructure.repository.OperationNonITRepository;
import org.mte.numecoeval.calculs.infrastructure.service.calcul.MainEquipementPhysiqueService;
import org.mte.numecoeval.calculs.infrastructure.service.calcul.MainMessagerieService;
import org.mte.numecoeval.calculs.infrastructure.service.calcul.MainOperationNonITService;
import org.mte.numecoeval.calculs.sync.generated.api.model.ReponseCalculRest;
import org.mte.numecoeval.calculs.sync.generated.api.model.SyncCalculRest;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;

@Service
@AllArgsConstructor
public class SyncCalculService {

    private EquipementPhysiqueRepository equipementPhysiqueRepository;
    private OperationNonITRepository operationNonITRepository;
    private MessagerieRepository messagerieRepository;
    private MainEquipementPhysiqueService mainEquipementPhysiqueService;
    private MainOperationNonITService mainOperationNonITService;
    private MainMessagerieService mainMessagerieService;

    public ReponseCalculRest calcul(SyncCalculRest syncCalculRest) {
        var result = new ReponseCalculRest();

        if (syncCalculRest.getEquipementPhysiqueIds() != null && !syncCalculRest.getEquipementPhysiqueIds().isEmpty()) {
            List<CalculSizes> calculSizesList = equipementPhysiqueRepository.findEquipementPhysiqueDTOs(syncCalculRest.getEquipementPhysiqueIds()).stream()
                    .map(equipementPhysiqueDTO -> mainEquipementPhysiqueService.calcul(equipementPhysiqueDTO))
                    .filter(Objects::nonNull)
                    .toList();

            result.setNbrEquipementPhysique(calculSizesList.stream().map(CalculSizes::getNbEquipementPhysique).reduce(0L, Long::sum));
            result.setNbrEquipementVirtuel(calculSizesList.stream().map(CalculSizes::getNbEquipementVirtuel).reduce(0L, Long::sum));
            result.setNbrApplication(calculSizesList.stream().map(CalculSizes::getNbApplication).reduce(0L, Long::sum));
        }
        if (syncCalculRest.getOperationNonITIds() != null && !syncCalculRest.getOperationNonITIds().isEmpty()) {
            List<CalculSizes> calculSizesOperationNonITList = operationNonITRepository.findOperationNonITDTOs(syncCalculRest.getOperationNonITIds()).stream()
                    .map(operationNonITDTO -> mainOperationNonITService.calcul(operationNonITDTO))
                    .filter(Objects::nonNull)
                    .toList();
            result.setNbrOperationNonIT(calculSizesOperationNonITList.stream().map(CalculSizes::getNbOperationNonIT).reduce(0L, Long::sum));
        }
        if (syncCalculRest.getMessagerieIds() != null && !syncCalculRest.getMessagerieIds().isEmpty()) {
            List<CalculSizes> calculSizesMessagerieList = messagerieRepository.findMessagerieDTOList(syncCalculRest.getMessagerieIds()).stream()
                    .map(messagerieDTO -> mainMessagerieService.calcul(messagerieDTO))
                    .filter(Objects::nonNull)
                    .toList();
            result.setNbrMessagerie(calculSizesMessagerieList.stream().map(CalculSizes::getNbMessagerie).reduce(0L, Long::sum));
        }
        return result;
    }
}
