package cokr.xit.ens.modules.common.ctgy.intgrnnoti.domain.repository;

import cokr.xit.ens.core.utils.CmmnUtil;
import cokr.xit.ens.modules.common.ctgy.intgrnnoti.domain.TmpltMngIntgrn;
import cokr.xit.ens.modules.common.ctgy.intgrnnoti.model.TmpltMngIntgrnDTO;
import cokr.xit.ens.modules.common.ctgy.sys.mng.model.TmpltMngSearchDTO;
import cokr.xit.ens.modules.kkoalimtalk.model.TmpltMngKkoAlimtalkDTO;
import cokr.xit.ens.modules.kkomydoc.model.TmpltMngKkoMydocDTO;
import cokr.xit.ens.modules.ktsigntalk.direct.model.TmpltMngKtSigntalkDTO;
import cokr.xit.ens.modules.ktsigntalk.gibis.model.TmpltMngKtGibisDTO;
import cokr.xit.ens.modules.nvsigntalk.model.TmpltMngNvSigntalkDTO;
import com.google.gson.Gson;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Projections;
import com.querydsl.core.types.QBean;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;

import java.util.List;
import java.util.Optional;

import static cokr.xit.ens.modules.common.ctgy.intgrnnoti.domain.QTmpltMngIntgrn.tmpltMngIntgrn;
import static cokr.xit.ens.modules.common.ctgy.sys.mng.domain.QOrgMng.orgMng;
import static cokr.xit.ens.modules.kkoalimtalk.domain.QTmpltMngKkoAlimtalk.tmpltMngKkoAlimtalk;
import static cokr.xit.ens.modules.kkomydoc.domain.QTmpltMngKkoMydoc.tmpltMngKkoMydoc;
import static cokr.xit.ens.modules.ktsigntalk.direct.domain.QTmpltMngKtSigntalk.tmpltMngKtSigntalk;
import static cokr.xit.ens.modules.ktsigntalk.gibis.domain.QTmpltMngKtGibis.tmpltMngKtGibis;
import static cokr.xit.ens.modules.nvsigntalk.domain.QTmpltMngNvSigntalk.tmpltMngNvSigntalk;

@RequiredArgsConstructor
public class TmpltMngIntgrnRepositoryImpl implements TmpltMngIntgrnRepositoryCustom {

    private final JPAQueryFactory query;

    @Override
    public Optional<TmpltMngIntgrn> findFetchByOrgCdAndTmpltCd(String orgCd, String tmpltCd) {
        return Optional.ofNullable(query.selectFrom(tmpltMngIntgrn)
                .where(tmpltMngIntgrn.orgMng.orgCd.eq(orgCd)
                        .and(tmpltMngIntgrn.tmpltCd.eq(tmpltCd)))
                .fetchOne());
    }

    @Override
    public List<TmpltMngIntgrn> findAllFetchBySearchDTO(TmpltMngSearchDTO searchDTO) {
        return query.selectFrom(tmpltMngIntgrn)
                .innerJoin(tmpltMngIntgrn.orgMng, orgMng)
                .fetchJoin()
                .where(eqSearchDTO(searchDTO))
                .fetch();
    }

    @Override
    public Optional<TmpltMngIntgrnDTO> findDtoByOrgCdAndTmpltCd(String orgCd, String tmpltCd) {
        return Optional.ofNullable(query.select(mappedDto())
                .from(tmpltMngIntgrn)
                .leftJoin(tmpltMngKkoAlimtalk).on(tmpltMngIntgrn.orgMng.orgCd.eq(tmpltMngKkoAlimtalk.orgMng.orgCd).and(tmpltMngIntgrn.tmpltCd.eq(tmpltMngKkoAlimtalk.tmpltCd)))
                .leftJoin(tmpltMngKkoMydoc).on(tmpltMngIntgrn.orgMng.orgCd.eq(tmpltMngKkoMydoc.orgMng.orgCd).and(tmpltMngIntgrn.tmpltCd.eq(tmpltMngKkoMydoc.tmpltCd)))
                .leftJoin(tmpltMngNvSigntalk).on(tmpltMngIntgrn.orgMng.orgCd.eq(tmpltMngNvSigntalk.orgMng.orgCd).and(tmpltMngIntgrn.tmpltCd.eq(tmpltMngNvSigntalk.tmpltCd)))
                .leftJoin(tmpltMngKtSigntalk).on(tmpltMngIntgrn.orgMng.orgCd.eq(tmpltMngKtSigntalk.orgMng.orgCd).and(tmpltMngIntgrn.tmpltCd.eq(tmpltMngKtSigntalk.tmpltCd)))
                .leftJoin(tmpltMngKtGibis).on(tmpltMngIntgrn.orgMng.orgCd.eq(tmpltMngKtGibis.orgMng.orgCd).and(tmpltMngIntgrn.tmpltCd.eq(tmpltMngKtGibis.tmpltCd)))
                .where(tmpltMngIntgrn.orgMng.orgCd.eq(orgCd)
                        .and(tmpltMngIntgrn.tmpltCd.eq(tmpltCd)))
                .fetchOne());
    }

    @Override
    public List<TmpltMngIntgrnDTO> findAllDtoBySearchDTO(TmpltMngSearchDTO searchDTO) {
        return query.select(mappedDto())
                .from(tmpltMngIntgrn)
                .leftJoin(tmpltMngKkoAlimtalk).on(tmpltMngIntgrn.orgMng.orgCd.eq(tmpltMngKkoAlimtalk.orgMng.orgCd).and(tmpltMngIntgrn.tmpltCd.eq(tmpltMngKkoAlimtalk.tmpltCd)))
                .leftJoin(tmpltMngKkoMydoc).on(tmpltMngIntgrn.orgMng.orgCd.eq(tmpltMngKkoMydoc.orgMng.orgCd).and(tmpltMngIntgrn.tmpltCd.eq(tmpltMngKkoMydoc.tmpltCd)))
                .leftJoin(tmpltMngNvSigntalk).on(tmpltMngIntgrn.orgMng.orgCd.eq(tmpltMngNvSigntalk.orgMng.orgCd).and(tmpltMngIntgrn.tmpltCd.eq(tmpltMngNvSigntalk.tmpltCd)))
                .leftJoin(tmpltMngKtSigntalk).on(tmpltMngIntgrn.orgMng.orgCd.eq(tmpltMngKtSigntalk.orgMng.orgCd).and(tmpltMngIntgrn.tmpltCd.eq(tmpltMngKtSigntalk.tmpltCd)))
                .leftJoin(tmpltMngKtGibis).on(tmpltMngIntgrn.orgMng.orgCd.eq(tmpltMngKtGibis.orgMng.orgCd).and(tmpltMngIntgrn.tmpltCd.eq(tmpltMngKtGibis.tmpltCd)))
                .where(eqSearchDTO(searchDTO))
                .fetch();
    }

    private QBean<TmpltMngIntgrnDTO> mappedDto() {
        Gson gson = new Gson();
        return Projections.fields(TmpltMngIntgrnDTO.class
                , tmpltMngIntgrn.dtype
                , tmpltMngIntgrn.orgMng.orgCd
                , tmpltMngIntgrn.orgMng.orgNm
                , tmpltMngIntgrn.tmpltCd
                , tmpltMngIntgrn.title
                , tmpltMngIntgrn.message
                , tmpltMngIntgrn.useYn
                , tmpltMngIntgrn.try1
                , tmpltMngIntgrn.try2
                , tmpltMngIntgrn.try3
                , Projections.fields(TmpltMngKkoAlimtalkDTO.class
                        , tmpltMngKkoAlimtalk.biztalkOrgCd
                        , tmpltMngKkoAlimtalk.biztalkTmpltCode
                        , tmpltMngKkoAlimtalk.pryMessage
                ).as("kkoAlimtalk")
                , Projections.fields(TmpltMngKkoMydocDTO.class
                        , tmpltMngKkoMydoc.csNumber
                        , tmpltMngKkoMydoc.csName
                        , tmpltMngKkoMydoc.ciTransUseYn
                        , tmpltMngKkoMydoc.tmpltMsgUseYn
                        , tmpltMngKkoMydoc.tmpltCsInfoUseYn
                        , tmpltMngKkoMydoc.pryMessage
                ).as("kkoMydoc")
                , Projections.fields(TmpltMngNvSigntalkDTO.class
                        , tmpltMngNvSigntalk.callCenterNo
                        , tmpltMngNvSigntalk.ciTransUseYn
                        , tmpltMngNvSigntalk.tmpltMsgUseYn
                        , tmpltMngNvSigntalk.tmpltCsInfoUseYn
                        , tmpltMngNvSigntalk.messageDataFmt
                ).as("nvSigntalk")
                , Projections.fields(TmpltMngKtSigntalkDTO.class
                        , tmpltMngKtSigntalk.sndTelNo
                        , tmpltMngKtSigntalk.sendTel
                        , tmpltMngKtSigntalk.ciTransUseYn
                        , tmpltMngKtSigntalk.tmpltMsgUseYn
                        , tmpltMngKtSigntalk.tmpltCsInfoUseYn
                        , tmpltMngKtSigntalk.pryMessage
                ).as("ktSigntalk")
                , Projections.fields(TmpltMngKtGibisDTO.class
                        , tmpltMngKtGibis.msgCd
                        , tmpltMngKtGibis.mtype
                        , tmpltMngKtGibis.msgType
                        , tmpltMngKtGibis.optType
                        , tmpltMngKtGibis.sndTelNo
                        , tmpltMngKtGibis.sendTel
                        , tmpltMngKtGibis.ciTransUseYn
                        , tmpltMngKtGibis.tmpltMsgUseYn
                        , tmpltMngKtGibis.tmpltCsInfoUseYn
                        , tmpltMngKtGibis.pryMessage
                ).as("ktGibis")
        );
    }

    @Override
    public Optional<TmpltMngIntgrn> findFetchByOrgCdAndTmpltCdAndUseYn(String orgCd, String tmpltCd, String useYn) {
        return Optional.ofNullable(
                query.selectFrom(tmpltMngIntgrn)
                        .innerJoin(tmpltMngIntgrn.orgMng, orgMng).fetchJoin()
                        .where(
                                tmpltMngIntgrn.orgMng.orgCd.eq(orgCd)
                                        .and(tmpltMngIntgrn.tmpltCd.eq(tmpltCd))
                                        .and(tmpltMngIntgrn.useYn.eq(useYn))
                        )
                        .fetchOne());
    }

    private BooleanBuilder eqSearchDTO(TmpltMngSearchDTO searchDTO) {
        BooleanBuilder builder = new BooleanBuilder();

        if (!CmmnUtil.isEmpty(searchDTO.getSchOrgCd()))
            builder.and(tmpltMngIntgrn.orgMng.orgCd.eq(searchDTO.getSchOrgCd()));

        if (!CmmnUtil.isEmpty(searchDTO.getSchTmpltCd()))
            builder.and(tmpltMngIntgrn.tmpltCd.eq(searchDTO.getSchTmpltCd()));

        if (!CmmnUtil.isEmpty(searchDTO.getSchTitle()))
            builder.and(tmpltMngIntgrn.title.like(searchDTO.getSchTitle() + "%"));


        return builder;
    }
}
