package cokr.xit.ens.biz.iup.domain.repository;

import cokr.xit.ens.biz.iup.code.IupSendTypeCd;
import cokr.xit.ens.biz.iup.domain.TbInputDataXit;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.BillReqSeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.BillSeCd;
import com.querydsl.core.types.dsl.DateTemplate;
import com.querydsl.core.types.dsl.Expressions;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Optional;

import static cokr.xit.ens.biz.iup.domain.QFsJob.fsJob;
import static cokr.xit.ens.biz.iup.domain.QTbInputDataXit.tbInputDataXit;
import static cokr.xit.ens.biz.iup.domain.QTbInputXit.tbInputXit;
import static cokr.xit.ens.modules.common.ctgy.intgrnbill.support.entity.QBillHist.billHist;
import static cokr.xit.ens.modules.common.ctgy.intgrnnoti.domain.QIntgrnSendDetail.intgrnSendDetail;
import static cokr.xit.ens.modules.kkoalimtalk.domain.QSendDetailKkoAlimtalk.sendDetailKkoAlimtalk;

@Slf4j
@Repository
@RequiredArgsConstructor
public class TbInputDataXitCustomRepositoryImpl implements TbInputDataXitCustomRepository<TbInputDataXit> {

    private final JPAQueryFactory query;

    @Override
    public Optional<TbInputDataXit> findFetchByDataId(String dataId) {
        return Optional.ofNullable(query.selectFrom(tbInputDataXit)
                .innerJoin(tbInputDataXit.tbInputXit, tbInputXit)
                .fetchJoin()
                .innerJoin(tbInputXit.fsJob, fsJob)
                .fetchJoin()
                .where(tbInputDataXit.dataId.eq(dataId))
                .fetchOne());
    }

    @Override
    public List<TbInputDataXit> findAllFetchByLnkInputId(Long lnkInputId) {
        return query.selectFrom(tbInputDataXit)
                .innerJoin(tbInputDataXit.tbInputXit, tbInputXit).fetchJoin()
                .innerJoin(tbInputXit.fsJob, fsJob).fetchJoin()
                .where(tbInputDataXit.tbInputXit.lnkInputId.eq(lnkInputId))
                .fetch();
    }


    @Override
    public String findDataIdFirstByLnkInputId(Long lnkInputId) {
        return query.select(tbInputDataXit.dataId)
                .from(tbInputDataXit)
                .where(tbInputDataXit.tbInputXit.lnkInputId.eq(lnkInputId))
                .fetchFirst();
    }


    @Override
    public Optional<Long> findLastSendMastIdByLnkInputIdAndSendType(Long lnkInputId, IupSendTypeCd sendTypeCd) {
        if (IupSendTypeCd.KP.equals(sendTypeCd))
//            return Optional.ofNullable(query.select(sendDetailKkoMydoc.sendMast.sendMastId)
//                    .from(sendDetailKkoMydoc)
////                    .where(sendDetailKkoMydoc.propExternalDocumentUuid.in(findDataIdsByLnkInputId(lnkInputId)))
//                    .where(sendDetailKkoMydoc.propExternalDocumentUuid.eq(findExternalDocumentUuidByLnkInputId(lnkInputId)))
//                    .groupBy(sendDetailKkoMydoc.sendMast.sendMastId)
//                    .orderBy(sendDetailKkoMydoc.sendMast.sendMastId.desc())
//                    .fetchFirst());
            return Optional.ofNullable(query.select(intgrnSendDetail.intgrnSendMast.intSendMastId)
                    .from(intgrnSendDetail)
                    .where(intgrnSendDetail.linkedUuid.eq(findExternalDocumentUuidByLnkInputId(lnkInputId)))
                    .groupBy(intgrnSendDetail.intgrnSendMast.intSendMastId)
                    .orderBy(intgrnSendDetail.intgrnSendMast.intSendMastId.desc())
                    .fetchFirst());
        else if (IupSendTypeCd.NI.equals(sendTypeCd))
            return Optional.ofNullable(query.select(sendDetailKkoAlimtalk.sendMast.sendMastId)
                    .from(sendDetailKkoAlimtalk)
//                    .where(sendDetailKkoAlimtalk.msgIdx.in(findDataIdsByLnkInputId(lnkInputId)))
                    .where(sendDetailKkoAlimtalk.msgIdx.eq(findExternalDocumentUuidByLnkInputId(lnkInputId)))
                    .groupBy(sendDetailKkoAlimtalk.sendMast.sendMastId)
                    .orderBy(sendDetailKkoAlimtalk.sendMast.sendMastId.desc())
                    .fetchFirst());
        else
            return Optional.ofNullable(null);
    }

    private String findExternalDocumentUuidByLnkInputId(Long lnkInputId) {
        return query.select(tbInputDataXit.linkedUuid)
                .from(tbInputDataXit)
                .where(tbInputDataXit.tbInputXit.lnkInputId.eq(lnkInputId))
                .fetchFirst();
    }


    @Override
    public List<TbInputDataXit> findAllByNoFwdPayResult() {
        LocalDateTime fromDate = LocalDateTime.of(2022, 07, 04, 00, 00, 00);
        LocalDateTime toDate = LocalDateTime.of(2022, 07, 05, 15, 00, 00);

        DateTemplate from = Expressions.dateTemplate(LocalDateTime.class, "TO_DATE({0}, {1})", fromDate.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")), "yyyyMMddHH24miss");
        DateTemplate to = Expressions.dateTemplate(LocalDateTime.class, "TO_DATE({0}, {1})", toDate.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")), "yyyyMMddHH24miss");
        return query.select(tbInputDataXit)
                .from(tbInputDataXit)
                .innerJoin(tbInputDataXit.tbInputXit, tbInputXit).fetchJoin()
//                .innerJoin(kkoBillHist).on(kkoBillHist.billerUserKey.eq(tbInputDataXit.linkedUuid)).fetchJoin()
                .innerJoin(billHist).on(billHist.billSe.eq(BillSeCd.bpKko).and(billHist.linkedUuid.eq(tbInputDataXit.linkedUuid))).fetchJoin()
                .where(
                        billHist.reqSe.eq(BillReqSeCd.US_PAYRSLT)
                                .and(tbInputXit.runDt.between(from, to))
                                .and(billHist.registDt.between(from, to))
                )
                .fetch();
    }
}
