package com.sonymusic.dx.dxuiservice.service;

import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.sonymusic.dx.dxuiservice.dto.ParticipantDTO;
import com.sonymusic.dx.persistence.gras.Company;
import com.sonymusic.dx.persistence.gras.DataSource;
import com.sonymusic.dx.persistence.gras.Participant;
import com.sonymusic.dx.persistence.gras.ParticipantSubType;
import com.sonymusic.dx.persistence.gras.ParticipantType;

import jakarta.persistence.EntityManager;
import jakarta.persistence.NoResultException;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.Tuple;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Join;
import jakarta.persistence.criteria.JoinType;
import jakarta.persistence.criteria.Root;


@Service
public class ParticipantService {

    @PersistenceContext(name = "dx-gras-persistence")
    private EntityManager em;

    private final Logger log = LoggerFactory.getLogger(getClass());

    public ParticipantDTO getParticipantById(Long participantNo) {

        ParticipantDTO participantDTO =null;
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<ParticipantDTO> repCQ = cb.createQuery(ParticipantDTO.class);
        Root<Participant> repRoot = repCQ.from(Participant.class);
        Join<Participant, DataSource> dataSourceJoin = repRoot.join("dataSource", JoinType.LEFT);
        Join<Participant, ParticipantType> participantTypeJoin = repRoot.join("participantType",JoinType.LEFT);
        Join<Participant, ParticipantSubType> participantSubTypeJoin = repRoot.join("subTypes",JoinType.LEFT);
        Join<Participant, Company> companyJoin = repRoot.join("initiatedByCompany", JoinType.LEFT);
//        Join<Company,RepertoireOwner>repertoireOwnerJoin= cb.treat(companyJoin.join("repOwnerKey",JoinType.LEFT), RepertoireOwner.class);
        repCQ.select(cb.construct(
                ParticipantDTO.class,
                repRoot.get("participantNo"),repRoot.get("fullName"),repRoot.get("firstName"),
                repRoot.get("lastName"),repRoot.get("bleed"),repRoot.get("indexName"),
                repRoot.get("legalFirstName"),repRoot.get("legalLastName"),repRoot.get("isPreferredParticipant"),
                repRoot.get("mostFrequestTasks"),repRoot.get("mainArtistCount"),repRoot.get("dateInitiated"),
                repRoot.get("characteriscsTextId"),dataSourceJoin.get("dataSourceName"),participantTypeJoin.get("participantTypeName"),
//                repertoireOwnerJoin.get("company").get("companyName"),
                companyJoin.get("companyName"),
                repRoot.get("initiatedByGRASUser"),
                repRoot.get("isni"),
                cb.literal("")

        )).where(cb.equal(repRoot.get("participantNo"),participantNo));
        repCQ.distinct(true);
        try {
            participantDTO =em.createQuery(repCQ).getSingleResult();
        }catch (NoResultException e){
            return participantDTO =null;
        }

        CriteriaQuery<Tuple> subTypeCQ = cb.createTupleQuery();
        Root<Participant> pRoot = subTypeCQ.from(Participant.class);
        Join<Participant,ParticipantSubType> subTypeJoin=pRoot.join("subTypes",JoinType.LEFT);
       subTypeCQ.multiselect(subTypeJoin.get("participantSubTypeName")).distinct(true)
               .where(cb.equal(pRoot.get("participantNo"),participantNo));

        List<Tuple> results = em.createQuery(subTypeCQ).getResultList();
        if (!results.isEmpty()){
            List<String> subType = results.stream().
                    map(t-> t.get(0,String.class)).filter(Objects::nonNull).collect(Collectors.toList());
            String subTypeCombined = String.join(";",subType);
            participantDTO.setSubType(subTypeCombined);
        }else {
            participantDTO.setSubType(null);
        }
        if (participantDTO.getMainArtistCount() >0){
            participantDTO.setMainArtist(true);
        }else {
            participantDTO.setMainArtist(false);
        }
        if (participantDTO.getDateInitiated() ==null) return null;
        participantDTO.setFormattedDateInitiated(new SimpleDateFormat("dd MMM yyyy").format(participantDTO.getDateInitiated()));
        return participantDTO;

    }
}
