package com.icomsys.main_vm.db.jpa.repo.scenario.dsl;

import com.google.gson.Gson;
import com.icomsys.main_vm.biz.rcp.conversation.vo.ConversationScenarioManagerRes;
import com.icomsys.main_vm.biz.rcp.conversation.vo.ConversationScenarioManagerSearchReq;
import com.icomsys.main_vm.biz.rcp.conversation.vo.ConversationScenarioReleaseRes;
import com.icomsys.main_vm.db.jpa.entity.conversation.QTbIntentMaster;
import com.icomsys.main_vm.db.jpa.entity.scenario.QTbScenarioMaster;
import com.icomsys.main_vm.db.jpa.entity.scenario.QTbScenarioRelatedIntent;
import com.icomsys.main_vm.db.jpa.entity.scenario.QTbScenarioRelease;
import com.icomsys.main_vm.db.jpa.entity.system.QTbBotUser;
import com.querydsl.core.QueryResults;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Projections;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.core.types.dsl.Expressions;
import com.querydsl.jpa.JPAExpressions;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.Aspect;

@Aspect
@Slf4j
@RequiredArgsConstructor
public class TbScenarioManagerRepoDslImpl implements TbScenarioManagerRepoDsl {
    private final JPAQueryFactory queryFactory;

    private QTbScenarioMaster qTbScenarioMaster = QTbScenarioMaster.tbScenarioMaster;
    private QTbScenarioRelease qTbScenarioRelease = QTbScenarioRelease.tbScenarioRelease;
    private QTbScenarioRelatedIntent qTbScenarioRelatedIntent = QTbScenarioRelatedIntent.tbScenarioRelatedIntent;
    private QTbIntentMaster qTbIntentMaster = QTbIntentMaster.tbIntentMaster;
    private QTbBotUser qTbBotUser = QTbBotUser.tbBotUser;

    @Override
    public QueryResults<ConversationScenarioManagerRes> searchScenarioList(ConversationScenarioManagerSearchReq dto) {
        log.info(new Gson().toJson(dto));
        QueryResults<ConversationScenarioManagerRes> result =
                queryFactory.select(
                                Projections.fields(
                                        ConversationScenarioManagerRes.class,
                                        qTbScenarioMaster.seq,
                                        qTbScenarioMaster.scenarioName,
                                        qTbBotUser.userName.as("updateName"),
                                        qTbScenarioMaster.updateDate,
                                        qTbScenarioRelease.version,
                                        ExpressionUtils.as(
                                                JPAExpressions.select(Expressions.stringTemplate("group_concat({0})", qTbIntentMaster.intentName))
                                                        .from(qTbScenarioRelatedIntent)
                                                        .innerJoin(qTbIntentMaster).on(qTbScenarioRelatedIntent.intentSeq.eq(qTbIntentMaster.seq))
                                                        .where(qTbScenarioRelatedIntent.scenarioSeq.eq(qTbScenarioMaster.seq)),
                                                "relatedIntents")
                                )
                        )
                        .from(qTbScenarioMaster)
                        .leftJoin(qTbScenarioRelease).on(qTbScenarioMaster.seq.eq(qTbScenarioRelease.masterSeq))
                        .innerJoin(qTbBotUser).on(qTbScenarioMaster.updateId.eq(qTbBotUser.userId))
                        .where( oprMngCodeEq(dto)
                                , scenarioNameEq(dto)
                                , qTbScenarioMaster.useYn.eq("Y")
                                , qTbScenarioRelease.releaseYn.eq("Y")
                                        .or(qTbScenarioRelease.releaseYn.isNull())
                        )
                        .limit(dto.getSize())
                        .offset(dto.getPage() * dto.getSize())
                        .orderBy(qTbScenarioMaster.updateDate.desc())
                        .fetchResults();

        return result;
    }

    private BooleanExpression scenarioNameEq(ConversationScenarioManagerSearchReq dto) {
        if (dto.getScenarioName() == null || dto.getScenarioName().equals("")) {
            return null;
        } else {
            return qTbScenarioMaster.scenarioName.contains(dto.getScenarioName());
        }
    }

    private BooleanExpression oprMngCodeEq(ConversationScenarioManagerSearchReq dto) {
        if (dto.getCustCode() == null || dto.getCustCode().equals("")) {
            return null;
        } else if (dto.getServiceGroup() == null || dto.getServiceGroup().equals("")) {
            return null;
        } else {
            return qTbScenarioMaster.oprMngCode.eq(dto.getCustCode() + "_RCP_" + dto.getServiceGroup());
        }
    }

    @Override
    public QueryResults<ConversationScenarioReleaseRes> searchScenarioReleaseList(ConversationScenarioManagerSearchReq dto){
        log.info(new Gson().toJson(dto));
        QueryResults<ConversationScenarioReleaseRes> result =
                queryFactory.select(
                                Projections.fields(
                                        ConversationScenarioReleaseRes.class,
                                        qTbScenarioRelease.seq,
                                        qTbScenarioRelease.version,
                                        qTbScenarioRelease.releaseYn,
                                        qTbBotUser.userName.as("registName"),
                                        qTbScenarioRelease.registDate
                                )
                        )
                        .from(qTbScenarioRelease)
                        .leftJoin(qTbBotUser).on(qTbScenarioRelease.registId.eq(qTbBotUser.userId))
                        .where( scenarioReleaseMasterSeqEq(dto))
                        .limit(dto.getSize())
                        .offset(dto.getPage() * dto.getSize())
                        .orderBy(qTbScenarioRelease.version.desc())
                        .fetchResults();
        return result;
    }

    private BooleanExpression scenarioReleaseMasterSeqEq(ConversationScenarioManagerSearchReq dto) {
        if (dto.getScenarioMasterSeq() == null ) {  // masterSeq가 없을 경우 -1로 조회하여 조회결과 없도록 처리
            return qTbScenarioRelease.masterSeq.eq(-1L);
        } else {
            return qTbScenarioRelease.masterSeq.eq(dto.getScenarioMasterSeq());
        }
    }

}
