package io.gmss.fiscad.service.worker;

import io.gmss.fiscad.entities.infocad.metier.*;
import io.gmss.fiscad.entities.infocad.parametre.Bloc;
import io.gmss.fiscad.entities.infocad.parametre.Personne;
import io.gmss.fiscad.entities.metadata.MobileDataEnquete;
import io.gmss.fiscad.entities.metadata.MobileDataUpload;
import io.gmss.fiscad.entities.rfu.metier.EnqueteBatiment;
import io.gmss.fiscad.entities.rfu.metier.EnqueteUniteLogement;
import io.gmss.fiscad.entities.rfu.parametre.ZoneRfu;
import io.gmss.fiscad.entities.user.User;
import io.gmss.fiscad.enums.TypeObjet;
import io.gmss.fiscad.paylaods.request.EnquetePayLoad;
import io.gmss.fiscad.paylaods.request.UploadPayLoad;
import io.gmss.fiscad.repositories.infocad.metier.*;
import io.gmss.fiscad.repositories.infocad.parametre.BlocRepository;
import io.gmss.fiscad.repositories.infocad.parametre.PersonneRepository;
import io.gmss.fiscad.repositories.metadata.MobileDataEnqueteRepository;
import io.gmss.fiscad.repositories.metadata.MobileDataUploadRepository;
import io.gmss.fiscad.repositories.rfu.metier.*;
import io.gmss.fiscad.repositories.rfu.parametre.ZoneRfuRepository;
import io.gmss.fiscad.repositories.user.UserRepository;
import io.gmss.fiscad.service.LogService;
import lombok.RequiredArgsConstructor;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.Optional;

@Service
@RequiredArgsConstructor
public class EnqueteAsyncWorker {
    private final TpeRepository tpeRepository;
    private final ParcelleRepository parcelleRepository;
    private final EnqueteRepository enqueteRepository;
    private final EnqueteUniteLogementRepository enqueteUniteLogementRepository;
    private final EnqueteBatimentRepository enqueteBatimentRepository;
    private final UserRepository userRepository;
    private final ZoneRfuRepository zoneRfuRepository;
    private final UploadRepository uploadRepository;
    private final PieceRepository pieceRepository;
    private final BlocRepository blocRepository;
    private final MobileDataEnqueteRepository mobileDataEnqueteRepository;
    private final ActeurConcerneRepository acteurConcerneRepository;
    private final CaracteristiqueParcelleRepository caracteristiqueParcelleRepository;
    private final CaracteristiqueBatimentRepository caracteristiqueBatimentRepository;
    private final CaracteristiqueUniteLogementRepository caracteristiqueUniteLogementRepository;
    private final UniteLogementRepository uniteLogementRepository;
    private final BatimentRepository batimentRepository;
    private final LogService logService;
    //@Async("enqueteExecutor")
    public void traitementAsyncEnquete(MobileDataEnquete mobileDataEnquete) {
        EnquetePayLoad enquetePayLoad=mobileDataEnquete.getEnquetePayLoad();
        try {
            if (enquetePayLoad.getTerminalId() == null) {
                logService.logTraiementAsync(TypeObjet.ENQUETE, "Problème de terminal", "terminal non fourni : ", mobileDataEnquete.getId());
                return;
            } else {
                Optional<Tpe> optionalTpe = tpeRepository.findById(enquetePayLoad.getTerminalId());
                if (optionalTpe.isEmpty()) {
                    logService.logTraiementAsync(TypeObjet.ENQUETE, "Problème de terminal", "terminal inexistant : ", mobileDataEnquete.getId());
                    return;
                }
            }
            deleteFromCodeParcelle(enquetePayLoad.getCodeParcelle());

            if (enquetePayLoad.getUserId() == null) {
                logService.logTraiementAsync(TypeObjet.ENQUETE, "Problème d'enqueteur", "L'enquêteur n'est pas précisée: ", mobileDataEnquete.getId());
                return;
            } else {
                Optional<User> optionalUser = userRepository.findById(enquetePayLoad.getUserId());
                if (optionalUser.isEmpty()) {
                    logService.logTraiementAsync(TypeObjet.ENQUETE, "Problème d'enqueteur", "L'enquêteur précisé n'existe pas : ", mobileDataEnquete.getId());
                    return;
                }
            }

            if (enquetePayLoad.getZoneRfuId() != null)  {
                Optional<ZoneRfu> optionalZoneRfu = zoneRfuRepository.findById(enquetePayLoad.getZoneRfuId());
                if (optionalZoneRfu.isEmpty()) {
                    logService.logTraiementAsync(TypeObjet.ENQUETE, "Problème de zone rfu", "La zone rfu précisé n'existe pas : ", mobileDataEnquete.getId());
                    return;
                }
            }
            if (enquetePayLoad.getParcelleId() == null) {
                logService.logTraiementAsync(TypeObjet.ENQUETE, "Problème de parcelle", "La parcelle n'est pas précisée", mobileDataEnquete.getId());
                return;
            } else {
                Optional<Parcelle> optionalParcelle = parcelleRepository.findFirstByExternalKeyAndTerminal_Id(enquetePayLoad.getParcelleId(), enquetePayLoad.getTerminalId());
                if (optionalParcelle.isEmpty()) {
                    logService.logTraiementAsync(TypeObjet.ENQUETE, "Problème de parcelle", "La parcelle précisée n'existe pas", mobileDataEnquete.getId());
                    return;
                }
            }
            if (enquetePayLoad.getBlocId() == null) {
                logService.logTraiementAsync(TypeObjet.ENQUETE, "Problème de bloc", "Le bloc n'est pas précisé", mobileDataEnquete.getId());
                return;
            } else {
                Optional<Bloc> optionalBloc = blocRepository.findById(enquetePayLoad.getBlocId());
                if (optionalBloc.isEmpty()) {
                    logService.logTraiementAsync(TypeObjet.ENQUETE, "Problème de bloc", "Le bloc précisé n'existe pas", mobileDataEnquete.getId());
                    return;
                }
            }
            Enquete enquete = new Enquete();
            Optional<Enquete> optionalEnquete=Optional.empty();
            optionalEnquete = enqueteRepository.findByMobileDataId(mobileDataEnquete.getId());
            if (optionalEnquete.isPresent()) {
                enquete = optionalEnquete.get();
            }else {
                optionalEnquete = enqueteRepository.findFirstByExternalKeyAndTerminal_Id(enquetePayLoad.getExternalKey(),enquetePayLoad.getTerminalId());
                if (optionalEnquete.isPresent()) {
                    enquete=optionalEnquete.get();
                }
            }
            enquete.setMobileDataId(mobileDataEnquete.getId());
            enquete = getEnqueteFromEnquetePayLoad(enquete, enquetePayLoad);
            enqueteRepository.save(enquete);
            mobileDataEnquete.setTraiter(true);
            mobileDataEnqueteRepository.save(mobileDataEnquete);

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

    private Enquete getEnqueteFromEnquetePayLoad(Enquete enquete, EnquetePayLoad enquetePayLoad) {

        if (enquetePayLoad.getUserId() != null) {
            Optional<User> optionalUser = userRepository.findById(enquetePayLoad.getUserId());
            enquete.setUser(optionalUser.orElse(null));
        }
        if (enquetePayLoad.getZoneRfuId() != null) {
            Optional<ZoneRfu> optionalZoneRfu = zoneRfuRepository.findById(enquetePayLoad.getZoneRfuId());
            enquete.setZoneRfu(optionalZoneRfu.orElse(null));
        }

        if (enquetePayLoad.getParcelleId() != null) {
            Optional<Parcelle> optionalParcelle = parcelleRepository.findFirstByNupProvisoire(enquetePayLoad.getCodeParcelle());
            //Optional<Parcelle> optionalParcelle = parcelleRepository.findFirstByExternalKeyAndTerminal_Id(enquetePayLoad.getParcelleId(), enquetePayLoad.getTerminalId());
            enquete.setParcelle(optionalParcelle.orElse(null));
        }
        if (enquetePayLoad.getBlocId() != null) {
            Optional<Bloc> optionalBloc = blocRepository.findById(enquetePayLoad.getBlocId());
            enquete.setBloc(optionalBloc.orElse(null));
        }

        if (enquetePayLoad.getTerminalId() != null) {
            Optional<Tpe> optionalTpe = tpeRepository.findById(enquetePayLoad.getTerminalId());
            enquete.setTerminal(optionalTpe.orElse(null));
        }
        enquete.setParcelleExternalKey(enquetePayLoad.getParcelleId());
        enquete.setStatusEnquete(enquetePayLoad.getStatusEnquete());
        enquete.setLitige(enquetePayLoad.isLitige());
        enquete.setObservationParticuliere(enquetePayLoad.getObservationParticuliere());
        enquete.setDateEnquete(enquetePayLoad.getDateEnquete());
        enquete.setDateFinalisation(enquetePayLoad.getDateFinalisation());
        enquete.setExternalKey(enquetePayLoad.getExternalKey());
        enquete.setQuartierId(enquetePayLoad.getQuartierId());
        enquete.setArrondissementId(enquetePayLoad.getArrondissementId());
        enquete.setCommuneId(enquetePayLoad.getCommuneId());
        enquete.setCommuneId(enquetePayLoad.getCommuneId());
        enquete.setDepartementId(enquetePayLoad.getDepartementId());
        enquete.setNumeroProvisoir(enquetePayLoad.getNumeroProvisoir());
        enquete.setCodeParcelle(enquetePayLoad.getCodeParcelle());
        enquete.setNomProprietaireParcelle(enquetePayLoad.getNomProprietaireParcelle());
        enquete.setCodeEquipe(enquetePayLoad.getCodeEquipe());
        enquete.setNumeroTitreFoncier(enquetePayLoad.getNumeroTitreFoncier());

        enquete.setNumEnterParcelle(enquetePayLoad.getNumEnterParcelle());
        enquete.setNumRue(enquetePayLoad.getNumRue());
        enquete.setNomRue(enquetePayLoad.getNomRue());
        enquete.setEmplacement(enquetePayLoad.getEmplacement());
        enquete.setAltitude(enquetePayLoad.getAltitude());
        enquete.setPrecision(enquetePayLoad.getPrecision());
        enquete.setNbreCoProprietaire(enquetePayLoad.getNbreCoProprietaire());
        enquete.setNbreIndivisiaire(enquetePayLoad.getNbreIndivisiaire());
        enquete.setAutreAdresse(enquetePayLoad.getAutreAdresse());
        enquete.setSurface(enquetePayLoad.getSurface());
        enquete.setNbreBatiment(enquetePayLoad.getNbreBatiment());
        enquete.setNbrePiscine(enquetePayLoad.getNbrePiscine());
        enquete.setDateDebutExcemption(enquetePayLoad.getDateDebutExcemption());
        enquete.setDateFinExcemption(enquetePayLoad.getDateFinExcemption());
        enquete.setPersonneId(enquetePayLoad.getPersonneId());
        enquete.setAutreNumeroTitreFoncier(enquete.getAutreNumeroTitreFoncier());
        return enquete;
    }


    protected void deleteFromCodeParcelle(String codeParcelle) {
        Optional<Enquete> optionalEnquete = enqueteRepository.findFirstByCodeParcelle(codeParcelle);
        Long idEnquete = null;
        if (optionalEnquete.isPresent()) {
            idEnquete = optionalEnquete.get().getId();
        }
        if (idEnquete != null) {
            System.out.println("ENQUETE ID" + idEnquete);
            try {
                uploadRepository.deleteUploadByEnqueteId(idEnquete);
            } catch (Exception e) {

            }
            try {
                pieceRepository.deletePieceByEnqueteId(idEnquete);
            } catch (Exception e) {

            }
            try {
                acteurConcerneRepository.deleteActeurConcerneByEnquete(idEnquete);
            } catch (Exception e) {

            }
            try {
                caracteristiqueParcelleRepository.deleteAllByEnquete_Id(idEnquete);
            } catch (Exception e) {

            }

            try {
                caracteristiqueBatimentRepository.deleteByEnqueteId(idEnquete);
            } catch (Exception e) {

            }

            try {
                caracteristiqueUniteLogementRepository.deleteByEnqueteId(idEnquete);
            } catch (Exception e) {

            }

            try {
                enqueteBatimentRepository.deleteAllByEnquete_Id(idEnquete);
            } catch (Exception e) {

            }

            try {
                enqueteUniteLogementRepository.deleteAllByEnquete_id(idEnquete);
            } catch (Exception e) {

            }

            try {
                uniteLogementRepository.deleteByEnqueteId(idEnquete);
            } catch (Exception e) {

            }

            try {
                batimentRepository.deleteByEnqueteId(idEnquete);
            } catch (Exception e) {

            }
            try {
                enqueteRepository.deleteById(idEnquete);
            } catch (Exception e) {

            }
        }
    }
}
