package org.mte.numecoeval.calculs.domain.traceur;

import org.mte.numecoeval.calculs.domain.data.demande.DemandeCalculImpactEquipementVirtuel;
import org.mte.numecoeval.calculs.domain.data.trace.TraceCalculImpactEquipementVirtuel;
import org.mte.numecoeval.calculs.domain.exception.CalculImpactException;
import org.mte.numecoeval.calculs.domain.port.input.service.impl.CalculImpactEquipementVirtuelServiceImpl;

public class TraceCalculImpactVirtuelUtils {

    private TraceCalculImpactVirtuelUtils(){}

    public static TraceCalculImpactEquipementVirtuel buildTrace(DemandeCalculImpactEquipementVirtuel demandeCalcul) {
        if(CalculImpactEquipementVirtuelServiceImpl.cleRepartitionEstDisponible(demandeCalcul)) {
            return TraceCalculImpactEquipementVirtuel.builder()
                    .formule(getFormuleForCleRepartition(demandeCalcul))
                    .build();
        }
        else if(CalculImpactEquipementVirtuelServiceImpl.calculPourCalculEstDisponible(demandeCalcul)) {
            return TraceCalculImpactEquipementVirtuel.builder()
                    .formule(getFormuleWithTotalVCPU(demandeCalcul))
                    .nbTotalVCPU(demandeCalcul.getNbTotalVCPU())
                    .nbEquipementsVirtuels(demandeCalcul.getNbEquipementsVirtuels())
                    .build();
        }
        else if(CalculImpactEquipementVirtuelServiceImpl.calculPourStockageEstDisponible(demandeCalcul)) {
            return TraceCalculImpactEquipementVirtuel.builder()
                    .formule(getFormuleForStockage(demandeCalcul))
                    .stockageTotalVirtuel(demandeCalcul.getStockageTotalVirtuel())
                    .build();
        }

        return TraceCalculImpactEquipementVirtuel.builder()
                .formule(getFormuleWithNombreEquipementVirtuel(demandeCalcul))
                .nbTotalVCPU(demandeCalcul.getNbTotalVCPU())
                .nbEquipementsVirtuels(demandeCalcul.getNbEquipementsVirtuels())
                .build();
    }

    public static TraceCalculImpactEquipementVirtuel buildTraceErreur(CalculImpactException exception) {
        var message = "Erreur lors du calcul de l'impact d'équipement virtuel";
        if(exception != null) {
            message = exception.getErrorType() + " : " + exception.getMessage();
        }
        return TraceCalculImpactEquipementVirtuel.builder()
                .erreur(message)
                .build();
    }

    public static  String getFormuleWithTotalVCPU(DemandeCalculImpactEquipementVirtuel demandeCalcul){
        return "valeurImpactUnitaire = valeurImpactEquipementPhysique(%s) * equipementVirtuel.vCPU(%s) / nbvCPU(%s)"
                .formatted(
                        demandeCalcul.getImpactEquipement().getImpactUnitaire(),
                        demandeCalcul.getEquipementVirtuel().getVCPU(),
                        demandeCalcul.getNbTotalVCPU()
                        );
    }

    public static  String getFormuleForStockage(DemandeCalculImpactEquipementVirtuel demandeCalcul){
        return "valeurImpactUnitaire = valeurImpactEquipementPhysique(%s) * equipementVirtuel.capaciteStockage(%s) / stockageTotalVirtuel(%s)"
                .formatted(
                        demandeCalcul.getImpactEquipement().getImpactUnitaire(),
                        demandeCalcul.getEquipementVirtuel().getCapaciteStockage(),
                        demandeCalcul.getStockageTotalVirtuel()
                        );
    }

    public static  String getFormuleForCleRepartition(DemandeCalculImpactEquipementVirtuel demandeCalcul){
        return "valeurImpactUnitaire = valeurImpactEquipementPhysique(%s) * equipementVirtuel.cleRepartition(%s)"
                .formatted(
                        demandeCalcul.getImpactEquipement().getImpactUnitaire(),
                        demandeCalcul.getEquipementVirtuel().getCleRepartition()
                        );
    }

    public static  String getFormuleWithNombreEquipementVirtuel(DemandeCalculImpactEquipementVirtuel demandeCalcul){
        return "valeurImpactUnitaire = valeurImpactEquipementPhysique(%s) / nbVM(%s)"
                .formatted(
                        demandeCalcul.getImpactEquipement().getImpactUnitaire(),
                        demandeCalcul.getNbEquipementsVirtuels()
                );
    }
}
