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.jpa.repository.DonneesEntreesRepository;
import org.mte.numecoeval.expositiondonneesentrees.infrastructure.mapper.CalculRestMapper;
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 {

    @Value("${regle-par-defaut-duree-usage}")
    private String defaultDureeUsage;

    final CalculRestMapper calculRestMapper;

    final SoumissionCalculPort soumissionCalculPort;

    final SoumissionCalculSyncPort soumissionCalculSyncPort;
    final StatutPourCalculPort statutPourCalculPort;

    final DonneesEntreesRepository donneesEntreesRepository;

    @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: {}", demandeCalculRest.getNomLot(), modeDureeUsage, mode);
        var demandeCalcul = calculRestMapper.toDomain(demandeCalculRest);
        donneesEntreesRepository.updateDonneesEntreesDureeUsage(String.valueOf(modeDureeUsage), demandeCalculRest.getNomLot());

        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: {}", demandeCalculRest.getNomLot());
        var demandeCalcul = calculRestMapper.toDomain(demandeCalculRest);

        var soumission = soumissionCalculPort.rejeuCalcul(demandeCalcul);

        var responseBody = calculRestMapper.toRest(soumission);

        return ResponseEntity.ok(responseBody);
    }
}
