package io.gmss.fiscad.service.worker;

import io.gmss.fiscad.entities.decoupage.Commune;
import io.gmss.fiscad.entities.decoupage.Nationalite;
import io.gmss.fiscad.entities.infocad.metier.ActeurConcerne;
import io.gmss.fiscad.entities.infocad.metier.Enquete;
import io.gmss.fiscad.entities.infocad.metier.Piece;
import io.gmss.fiscad.entities.infocad.metier.Tpe;
import io.gmss.fiscad.entities.infocad.parametre.*;
import io.gmss.fiscad.entities.metadata.MobileDataPersonne;
import io.gmss.fiscad.entities.metadata.MobileDataPiece;
import io.gmss.fiscad.enums.Categorie;
import io.gmss.fiscad.enums.TypeObjet;
import io.gmss.fiscad.paylaods.request.PersonnePayLoad;
import io.gmss.fiscad.paylaods.request.PiecePayLoad;
import io.gmss.fiscad.repositories.decoupage.CommuneRepository;
import io.gmss.fiscad.repositories.decoupage.NationaliteRepository;
import io.gmss.fiscad.repositories.infocad.metier.*;
import io.gmss.fiscad.repositories.infocad.parametre.*;
import io.gmss.fiscad.repositories.metadata.MobileDataPersonneRepository;
import io.gmss.fiscad.repositories.metadata.MobileDataPieceRepository;
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 PieceAsyncWorker {
    private final TpeRepository tpeRepository;
    private final PersonneRepository personneRepository;
    private final EnqueteRepository enqueteRepository;
    private final SourceDroitRepository sourceDroitRepository;
    private final ModeAcquisitionRepository modeAcquisitionRepository;
    private final ActeurConcerneRepository acteurConcerneRepository;
    private final TypePieceRepository typePieceRepository;
    private final MobileDataPieceRepository mobileDataPieceRepository;
    private final PieceRepository pieceRepository;
    private final LogService logService;

    //@Async("pieceExecutor")
    public void traitementAsyncPiece(MobileDataPiece mobileDataPiece) {
        PiecePayLoad piecePayLoad=mobileDataPiece.getPiecePayLoad();
        try {
            if (piecePayLoad.getTerminalId() == null) {
                logService.logTraiementAsync(TypeObjet.PIECE, "Problème de terminal", "terminal non fourni : ", mobileDataPiece.getId());
                return;
            } else {
                Optional<Tpe> optionalTpe = tpeRepository.findById(piecePayLoad.getTerminalId());
                if (optionalTpe.isEmpty()) {
                    logService.logTraiementAsync(TypeObjet.PIECE, "Problème de terminal", "terminal inexistant : ", mobileDataPiece.getId());
                    return;
                }
            }
            Piece piece = new Piece();
            Optional<Piece> optionalPiece=Optional.empty();
            optionalPiece = pieceRepository.findByMobileDataId(mobileDataPiece.getId());
            if (optionalPiece.isPresent()) {
                piece = optionalPiece.get();
            }else {
                optionalPiece = pieceRepository.findFirstByExternalKeyAndTerminal_Id(piecePayLoad.getExternalKey(),piecePayLoad.getTerminalId());
                if (optionalPiece.isPresent()) {
                    piece=optionalPiece.get();
                }
            }
            piece.setMobileDataId(mobileDataPiece.getId());
            piece = getPieceFromPiecePayLoad(piece, piecePayLoad);
            pieceRepository.save(piece);
            mobileDataPiece.setTraiter(true);
            mobileDataPieceRepository.save(mobileDataPiece);
        } catch (Exception e) {
            logService.logTraiementAsync(TypeObjet.PIECE, "Erreur inattendue", e.getMessage(), mobileDataPiece.getId());
        }
    }


    private Piece getPieceFromPiecePayLoad(Piece piece, PiecePayLoad piecePayLoad) {
        if (piecePayLoad.getTypePieceId() != null) {
            Optional<TypePiece> optionalTypePiece = typePieceRepository.findById(piecePayLoad.getTypePieceId());
            piece.setTypePiece(optionalTypePiece.orElse(null));
        } else {
            piece.setTypePiece(null);
        }
        if (piecePayLoad.getPersonneId() != null) {
            Optional<Personne> optionalPersonne = personneRepository.findFirstByExternalKeyAndTerminal_Id(piecePayLoad.getPersonneId(), piecePayLoad.getTerminalId());
            piece.setPersonne(optionalPersonne.orElse(null));
        } else {
            piece.setPersonne(null);
        }
        if (piecePayLoad.getActeurConcerneId() != null) {
            Optional<ActeurConcerne> optionalActeurConcerne = acteurConcerneRepository.findFirstByExternalKeyAndTerminal_Id(piecePayLoad.getActeurConcerneId(), piecePayLoad.getTerminalId());
            piece.setActeurConcerne(optionalActeurConcerne.orElse(null));
        } else {
            piece.setActeurConcerne(null);
        }
        if (piecePayLoad.getModeAcquisitionId() != null) {
            Optional<ModeAcquisition> optionalModeAcquisition = modeAcquisitionRepository.findById(piecePayLoad.getModeAcquisitionId());
            piece.setModeAcquisition(optionalModeAcquisition.orElse(null));
        } else {
            piece.setModeAcquisition(null);
        }
        if (piecePayLoad.getSourceDroitId() != null) {
            Optional<SourceDroit> optionalSourceDroit = sourceDroitRepository.findById(piecePayLoad.getSourceDroitId());
            piece.setSourceDroit(optionalSourceDroit.orElse(null));
        } else {
            piece.setSourceDroit(null);
        }
        if (piecePayLoad.getTerminalId() != null) {
            Optional<Tpe> optionalTpe = tpeRepository.findById(piecePayLoad.getTerminalId());
            piece.setTerminal(optionalTpe.orElse(null));
        }

        if (piecePayLoad.getTerminalId() != null && piecePayLoad.getEnqueteId() != null) {
            Optional<Enquete> optionalEnquete = enqueteRepository.findFirstByExternalKeyAndTerminal_Id(piecePayLoad.getEnqueteId(), piecePayLoad.getTerminalId());
            if (optionalEnquete.isPresent()) {
                piece.setEnqueteId(optionalEnquete.get().getId());
            }
        }

        piece.setActeurConcerneExternalKey(piecePayLoad.getActeurConcerneId());
        piece.setPersonneExternalKey(piecePayLoad.getPersonneId());
        piece.setEnqueteExternalKey(piecePayLoad.getEnqueteId());
        piece.setNumeroPiece(piecePayLoad.getNumeroPiece());
        piece.setUrl(piecePayLoad.getUrl());
        piece.setExternalKey(piecePayLoad.getExternalKey());
        piece.setDateExpiration(piecePayLoad.getDateExpiration());
        piece.setMax_numero_piece_id(piecePayLoad.getMax_numero_piece_id());
        piece.setMax_numero_acteur_concerne_id(piecePayLoad.getMax_numero_acteur_concerne_id());
        piece.setEnqueteId(piecePayLoad.getEnqueteId());
        piece.setBlocId(piecePayLoad.getBlocId());
        piece.setEnqueteExternalKey(piecePayLoad.getEnqueteId());
        return piece;
    }
}
