package io.gmss.fiscad.service.worker;

import io.gmss.fiscad.entities.infocad.metier.ActeurConcerne;
import io.gmss.fiscad.entities.infocad.metier.Enquete;
import io.gmss.fiscad.entities.infocad.metier.Tpe;
import io.gmss.fiscad.entities.infocad.parametre.Personne;
import io.gmss.fiscad.entities.infocad.parametre.PositionRepresentation;
import io.gmss.fiscad.entities.infocad.parametre.TypeContestation;
import io.gmss.fiscad.entities.infocad.parametre.TypeRepresentation;
import io.gmss.fiscad.entities.metadata.MobileDataActeurConcerne;
import io.gmss.fiscad.enums.TypeObjet;
import io.gmss.fiscad.paylaods.request.ActeurConcernePayLoad;
import io.gmss.fiscad.repositories.infocad.metier.ActeurConcerneRepository;
import io.gmss.fiscad.repositories.infocad.metier.EnqueteRepository;
import io.gmss.fiscad.repositories.infocad.metier.TpeRepository;
import io.gmss.fiscad.repositories.infocad.parametre.PersonneRepository;
import io.gmss.fiscad.repositories.infocad.parametre.PositionRepresentationRepository;
import io.gmss.fiscad.repositories.infocad.parametre.TypeContestationRepository;
import io.gmss.fiscad.repositories.infocad.parametre.TypeRepresentationRepository;
import io.gmss.fiscad.repositories.metadata.MobileDataActeurConcerneRepository;
import io.gmss.fiscad.service.LogService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.Optional;

@Service
@RequiredArgsConstructor
public class ActeurConcerneAsyncWorker {
    private final TpeRepository tpeRepository;
    private final EnqueteRepository enqueteRepository;
    private final ActeurConcerneRepository acteurConcerneRepository;
    private final PersonneRepository personneRepository;
    private final MobileDataActeurConcerneRepository mobileDataActeurConcerneRepository;
    private final PositionRepresentationRepository positionRepresentationRepository;
    private final TypeContestationRepository typeContestationRepository;
    private final TypeRepresentationRepository typeRepresentationRepository;
    private final LogService logService;
    //@Async("acteurConcerneExecutor")
    public void traitementAsyncActeurConcerne(MobileDataActeurConcerne mobileDataActeurConcerne) {
        ActeurConcernePayLoad acteurConcernePayLoad=mobileDataActeurConcerne.getActeurConcernePayLoad();
        try {
            if (acteurConcernePayLoad.getTerminalId() == null) {
                logService.logTraiementAsync(TypeObjet.ACTEURCONCERNER, "Problème de terminal", "terminal non fourni : ", mobileDataActeurConcerne.getId());
                return;
            } else {
                Optional<Tpe> optionalTpe = tpeRepository.findById(acteurConcernePayLoad.getTerminalId());
                if (optionalTpe.isEmpty()) {
                    logService.logTraiementAsync(TypeObjet.ACTEURCONCERNER, "Problème de terminal", "terminal inexistant : ", mobileDataActeurConcerne.getId());
                    return;
                }
            }
            if (acteurConcernePayLoad.getPersonneId() == null) {
                logService.logTraiementAsync(TypeObjet.ACTEURCONCERNER, "Problème de Personne", "Id Personne non fournie : ", mobileDataActeurConcerne.getId());
                return;
            } else {
                Optional<Personne> optionalPersonne = personneRepository.findFirstByExternalKeyAndTerminal_Id(acteurConcernePayLoad.getPersonneId(), acteurConcernePayLoad.getTerminalId());
                if (optionalPersonne.isEmpty()) {
                    logService.logTraiementAsync(TypeObjet.ACTEURCONCERNER, "Problème de Personne", "La personne précisée n'existe pas : ", mobileDataActeurConcerne.getId());
                    return;
                }
            }

            if (acteurConcernePayLoad.getEnqueteId() == null) {
                logService.logTraiementAsync(TypeObjet.ACTEURCONCERNER, "Problème de enquete", "Id enquête non fournie : ", mobileDataActeurConcerne.getId());
                return ;
            } else {
                Optional<Enquete> optionalEnquete = enqueteRepository.findFirstByExternalKeyAndTerminal_Id(acteurConcernePayLoad.getEnqueteId(), acteurConcernePayLoad.getTerminalId());
                if (optionalEnquete.isEmpty()) {
                    logService.logTraiementAsync(TypeObjet.ACTEURCONCERNER, "Problème de enquête", "L'enquête précisée n'existe pas : ", mobileDataActeurConcerne.getId());
                    return;
                }
            }

            ActeurConcerne acteurConcerne = new ActeurConcerne();
            Optional<ActeurConcerne> optionalActeurConcerne=Optional.empty();
            optionalActeurConcerne = acteurConcerneRepository.findByMobileDataId(mobileDataActeurConcerne.getId());
            if (optionalActeurConcerne.isPresent()) {
                acteurConcerne = optionalActeurConcerne.get();
            }else {
                optionalActeurConcerne = acteurConcerneRepository.findFirstByExternalKeyAndTerminal_Id(acteurConcernePayLoad.getExternalKey(),acteurConcernePayLoad.getTerminalId());
                if (optionalActeurConcerne.isPresent()) {
                    acteurConcerne=optionalActeurConcerne.get();
                }
            }
            acteurConcerne.setMobileDataId(mobileDataActeurConcerne.getId());
            acteurConcerne = getActeurConcerneFromActeurConcernePayLoad(acteurConcerne, acteurConcernePayLoad);
            acteurConcerneRepository.save(acteurConcerne);
            mobileDataActeurConcerne.setTraiter(true);
            mobileDataActeurConcerneRepository.save(mobileDataActeurConcerne);

        } catch (Exception e) {
            logService.logTraiementAsync(TypeObjet.ACTEURCONCERNER, "Problème de inattendu", e.getMessage(), mobileDataActeurConcerne.getId());

        }
    }

    private ActeurConcerne getActeurConcerneFromActeurConcernePayLoad(ActeurConcerne acteurConcerne, ActeurConcernePayLoad acteurConcernePayLoad) {

        if (acteurConcernePayLoad.getEnqueteId() != null) {
            Optional<Enquete> optionalEnquete = enqueteRepository.findFirstByExternalKeyAndTerminal_Id(acteurConcernePayLoad.getEnqueteId(), acteurConcernePayLoad.getTerminalId());
            acteurConcerne.setEnquete(optionalEnquete.orElse(null));
        }
        if (acteurConcernePayLoad.getEnqueteId() != null) {
            Optional<Personne> optionalPersonne = personneRepository.findFirstByExternalKeyAndTerminal_Id(acteurConcernePayLoad.getPersonneId(), acteurConcernePayLoad.getTerminalId());
            acteurConcerne.setPersonne(optionalPersonne.orElse(null));
        }
        if (acteurConcernePayLoad.getPositionRepresentationId() != null) {
            Optional<PositionRepresentation> optionalPositionRepresentation = positionRepresentationRepository.findById(acteurConcernePayLoad.getPositionRepresentationId());
            acteurConcerne.setPositionRepresentation(optionalPositionRepresentation.orElse(null));
        }
        if (acteurConcernePayLoad.getTypeContestationId() != null) {
            Optional<TypeContestation> optionalTypeContestation = typeContestationRepository.findById(acteurConcernePayLoad.getTypeContestationId());
            acteurConcerne.setTypeContestation(optionalTypeContestation.orElse(null));
        }
        if (acteurConcernePayLoad.getTypeRepresentationId() != null) {
            Optional<TypeRepresentation> optionalTypeRepresentation = typeRepresentationRepository.findById(acteurConcernePayLoad.getTypeRepresentationId());
            acteurConcerne.setTypeRepresentation(optionalTypeRepresentation.orElse(null));
        }
        if (acteurConcernePayLoad.getTerminalId() != null) {
            Optional<Tpe> optionalTpe = tpeRepository.findById(acteurConcernePayLoad.getTerminalId());
            acteurConcerne.setTerminal(optionalTpe.orElse(null));
        }
        acteurConcerne.setEnqueteExternalKey(acteurConcernePayLoad.getEnqueteId());
        acteurConcerne.setPersonneExternalKey(acteurConcernePayLoad.getPersonneId());
        acteurConcerne.setPart(acteurConcernePayLoad.getPart());
        acteurConcerne.setTypeDroit(acteurConcernePayLoad.getTypeDroit());
        acteurConcerne.setExternalKey(acteurConcernePayLoad.getExternalKey());
        acteurConcerne.setRoleActeur(acteurConcernePayLoad.getRoleActeur());
        acteurConcerne.setBlocId(acteurConcernePayLoad.getBlocId());
        acteurConcerne.setHaveDeclarant(acteurConcernePayLoad.getHaveDeclarant());
        acteurConcerne.setMax_numero_acteur_concerne_id(acteurConcernePayLoad.getMax_numero_acteur_concerne_id());
        return acteurConcerne;
    }

}
