package org.mte.numecoeval.expositiondonneesentrees.infrastructure.controller;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.mte.numecoeval.expositiondonneesentrees.domain.ports.input.SoumissionCalculPort;
import org.mte.numecoeval.expositiondonneesentrees.domain.ports.input.SoumissionCalculSyncPort;
import org.mte.numecoeval.expositiondonneesentrees.domain.ports.input.StatutPourCalculPort;
import org.mte.numecoeval.expositiondonneesentrees.generated.api.model.*;
import org.mte.numecoeval.expositiondonneesentrees.generated.api.server.CalculsApi;
import org.mte.numecoeval.expositiondonneesentrees.infrastructure.mapper.CalculRestMapper;
import org.mte.numecoeval.expositiondonneesentrees.infrastructure.service.DonneesEntreesService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Slf4j
@RequiredArgsConstructor
public class CalculController implements CalculsApi {

    public static final String TYPE_CALCUL_REJEU = "rejeu";
    public static final String TYPE_CALCUL_SOUMISSION = "soumission";
    @Value("${regle-par-defaut-duree-usage}")
    private String defaultDureeUsage;

    final CalculRestMapper calculRestMapper;

    final SoumissionCalculPort soumissionCalculPort;

    final SoumissionCalculSyncPort soumissionCalculSyncPort;
    final StatutPourCalculPort statutPourCalculPort;
    final DonneesEntreesService donneesEntreesService;

    @Override
    public ResponseEntity<StatutCalculRest> statutPourCalcul(String nomLot, String nomOrganisation) {
        var statut = statutPourCalculPort.statutDesCalculs(nomLot, nomOrganisation);
        log.info("Statut global des calculs, nomOrganisation: {}, nomLot: {}. Avancement: {}", nomOrganisation, nomLot, statut.getEtat());
        return ResponseEntity.ok(statut);
    }

    @Override
    public ResponseEntity<RapportDemandeCalculRest> soumissionPourCalcul(DemandeCalculRest demandeCalculRest, DureeUsage dureeUsage, ModeRest mode) {

        var modeDureeUsage = dureeUsage == null ? DureeUsage.fromValue(defaultDureeUsage) : dureeUsage;
        if (DureeUsage.REEL != modeDureeUsage) {
            modeDureeUsage = DureeUsage.FIXE;
        }
        log.info("Soumission de calcul pour nom_lot: {}, dureeUsage: {}, mode: {}, etapes:{}, criteres:{}", demandeCalculRest.getNomLot(), modeDureeUsage, mode, demandeCalculRest.getEtapes(), demandeCalculRest.getCriteres());
        var demandeCalcul = calculRestMapper.toDomain(demandeCalculRest);

        donneesEntreesService.manageDonneesEntrees(demandeCalculRest.getNomLot(), dureeUsage, demandeCalculRest.getEtapes(), demandeCalculRest.getCriteres(), TYPE_CALCUL_SOUMISSION);

        var soumission = ModeRest.ASYNC == mode ?
                soumissionCalculPort.soumissionCalcul(demandeCalcul) :
                soumissionCalculSyncPort.soumissionCalcul(demandeCalcul);

        return ResponseEntity.ok(calculRestMapper.toRest(soumission));
    }


    @Override
    public ResponseEntity<RapportDemandeCalculRest> rejeuCalcul(DemandeCalculRest demandeCalculRest) {
        log.info("Rejeu de calcul, nom_lot: {}, etapes:{}, criteres:{}", demandeCalculRest.getNomLot(), demandeCalculRest.getEtapes(), demandeCalculRest.getCriteres());
        var demandeCalcul = calculRestMapper.toDomain(demandeCalculRest);

        donneesEntreesService.manageDonneesEntrees(demandeCalculRest.getNomLot(), null, demandeCalculRest.getEtapes(), demandeCalculRest.getCriteres(), TYPE_CALCUL_REJEU);

        var soumission = soumissionCalculPort.rejeuCalcul(demandeCalcul);

        var responseBody = calculRestMapper.toRest(soumission);

        return ResponseEntity.ok(responseBody);
    }
}
