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

import com.google.gson.Gson;
import com.icomsys.main_vm.biz.rcp.conversation.dto.IntentRequestDTO;
import com.icomsys.main_vm.biz.rcp.conversation.vo.SearchIntentListVo;
import com.icomsys.main_vm.biz.rcp.conversation.vo.SelectIntentListVo;
import com.icomsys.main_vm.biz.rcp.conversation.vo.SelectSlotIntentListVo;
import com.icomsys.main_vm.biz.rcp.conversation.vo.intent.ExcelIntentListVo;
import com.icomsys.main_vm.biz.rcp.conversation.vo.intent.IntentSearchVo;
import com.icomsys.main_vm.biz.rcp.conversation.vo.selectIntentEntityNameListVo;
import com.icomsys.main_vm.db.jpa.entity.conversation.*;
import com.icomsys.main_vm.db.jpa.entity.system.*;
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.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import static com.querydsl.sql.SQLExpressions.set;

@Aspect
@Slf4j
@RequiredArgsConstructor
public class TbIntentMasterRepoDslImpl implements TbIntentMasterRepoDsl {

    private final JPAQueryFactory queryFactory;
    private QTbIntentMaster qTbIntentMaster = QTbIntentMaster.tbIntentMaster;
    private QTbSlotMaster qTbSlotMaster = QTbSlotMaster.tbSlotMaster;
    private QTbSynonymMaster qTbSynonymMaster = QTbSynonymMaster.tbSynonymMaster;
    private QTbDictionaryMaster qTbDictionaryMaster = QTbDictionaryMaster.tbDictionaryMaster;
    private QTbBotCommonCode qTbBotCommonCode = QTbBotCommonCode.tbBotCommonCode;
    private QTbIntentExample qTbIntentExample = QTbIntentExample.tbIntentExample;

    @Override
    public List<SelectSlotIntentListVo> selectSlotIntentList(String opr) {

        var result = queryFactory.select(
                        Projections.fields(
                                SelectSlotIntentListVo.class,
                                qTbIntentMaster.oprMngCode,
                                qTbIntentMaster.intentName,
                                qTbSlotMaster.groupName,
                                qTbIntentMaster.seq.as("intentSeq")
                        )
                )
                .from(qTbIntentMaster)
                .leftJoin(qTbSlotMaster).on(qTbSlotMaster.oprMngCode.eq(qTbIntentMaster.oprMngCode))
                .where(qTbIntentMaster.useYn.eq("Y").and(qTbIntentMaster.oprMngCode.eq(opr)))
                .groupBy(qTbIntentMaster.intentName)
                .orderBy(qTbIntentMaster.updateDate.desc())
                .fetch();

        return result;
    }

    @Override
    public List<selectIntentEntityNameListVo> selectIntentEntityNameList(String opr, String entityType) {
        List<selectIntentEntityNameListVo> result = new ArrayList<>();

        //if문이 나을듯.
        switch (entityType) {
            case "B":
                result = queryFactory.select(
                                Projections.fields(selectIntentEntityNameListVo.class,
                                        qTbSynonymMaster.seq,
                                        qTbSynonymMaster.repWord.as("entityName")
                                )
                        ).from(qTbSynonymMaster)
                        .where(qTbSynonymMaster.useYn.eq("Y")
                                .and(qTbSynonymMaster.oprMngCode.eq(opr)))
                        .fetch();
                break;
            case "C":
                result = queryFactory.select(
                                Projections.fields(selectIntentEntityNameListVo.class,
                                        qTbDictionaryMaster.seq,
                                        qTbDictionaryMaster.repWord.as("entityName")
                                )
                        ).from(qTbDictionaryMaster)
                        .where(qTbDictionaryMaster.useYn.eq("Y")
                                .and(qTbDictionaryMaster.oprMngCode.eq(opr)))
                        .fetch();
                break;
        }
        return result;
    }

    @Override
    public List<SelectIntentListVo> selectIntentList(IntentSearchVo dto) {
        JPAQuery query = null;
        query = queryFactory.select(
                        Projections.fields(SelectIntentListVo.class,
                                qTbIntentMaster.seq,
                                qTbIntentMaster.oprMngCode,
                                qTbIntentMaster.intentName,
                                qTbIntentMaster.category,
                                qTbIntentMaster.registId,
                                qTbIntentMaster.registDate,
                                qTbIntentMaster.updateId,
                                qTbIntentMaster.updateDate,
                                qTbBotCommonCode.codeName,
                                ExpressionUtils.as(
                                        JPAExpressions.select(qTbIntentExample.count())
                                                .from(qTbIntentExample)
                                                .where(qTbIntentExample.intentSeq.eq(qTbIntentMaster.seq)
                                                        .and(qTbIntentExample.useYn.eq("Y")
                                                        )
                                                ), "exampleCnt")
                        )
                ).from(qTbIntentMaster)
                .innerJoin(qTbBotCommonCode).on(qTbIntentMaster.category.eq(qTbBotCommonCode.minorCode)
                        .and(qTbBotCommonCode.oprMngCode.eq(dto.getOprMngCodeUpper())))
                .where(qTbIntentMaster.useYn.eq("Y")
                        .and(qTbBotCommonCode.majorCode.eq("INTENT_GROUP")));  //INTENT_GROUP

        if (dto.getOprMngCode() != null && !(dto.getOprMngCode().equals(""))) {
            query.where(qTbIntentMaster.oprMngCode.eq(dto.getOprMngCode()));
        }
        if (dto.getCategory() != null && !(dto.getCategory().equals(""))) {
            query.where(qTbIntentMaster.category.eq(dto.getCategory()));
        }
        if (dto.getIntentName() != null && !(dto.getIntentName().equals(""))) {
            query.where(qTbIntentMaster.intentName.contains(dto.getIntentName()));
        }
        query.orderBy(qTbIntentMaster.registDate.desc());

        return query.fetch();


    }

/*        List<String> intentnames = null;
        String regExp = null;
        if (regExp !=null && !regExp.equals("")) {
            intentnames = new ArrayList<>();
            intentnames = Arrays.asList(regExp.trim().split("|"));
        }

        query.where(qTbIntentMaster.useYn.eq("Y")
//                        , qTbBotCommonCode.majorCode.eq("INTENT_GROUP")
                        , eqTbIntentMasterOprMngCode(oprMngCode)
                        , eqTbIntentMasterCategory(category)
                        //test case 없어서 확인 못해봄...
                        , eqTbIntentMasterIntentName(intentnames)
                )
                .orderBy(qTbIntentMaster.registDate.desc());

        return query.fetch();
    }

    private BooleanExpression eqTbIntentMasterOprMngCode(String oprMngCode) {
        return oprMngCode != null && !oprMngCode.equals("") && !oprMngCode.equals("ALL") ? qTbIntentMaster.oprMngCode.eq(oprMngCode) : null;
    }

    private BooleanExpression eqTbIntentMasterCategory(String category) {
        return category != null && !category.equals("") ? qTbIntentMaster.category.eq(category) : null;
    }

    //동작할지 모르겠음.
    private BooleanExpression eqTbIntentMasterIntentName(List<String> names) {
        return names != null ? Expressions.allOf(
                names.stream().map(this::isintentName)
                        .toArray(BooleanExpression[]::new)) : null;
    }

    private BooleanExpression isintentName(String intentName) {
        return qTbIntentMaster.intentName.contains(intentName);
    }*/


 /*    public void updateIntentMaster(HashMap eMap) {
       log.info("dto -> {}", new Gson().toJson(eMap));
        try {
            var query = queryFactory.update(qTbIntentMaster)
                    .set(qTbIntentMaster.updateId, eMap.get("updateId"))
                    .set(qTbIntentMaster.updateDate, LocalDateTime.now());
            if (dto.getIntentName() != null && !dto.getIntentName().equals("")) {
                query.set(qTbIntentMaster.intentName, dto.getIntentName());
            }
            if (dto.getCategory() != null && !dto.getCategory().equals("")) {
                query.set(qTbIntentMaster.category, dto.getCategory());
            }
            if (dto.getUseYn() != null && !dto.getUseYn().equals("")) {
                query.set(qTbIntentMaster.useYn, dto.getUseYn());
            }
            query.where(qTbIntentMaster.seq.eq(Long.valueOf(dto.getSeq())));
            query.execute();
        }catch (Exception e){
            e.printStackTrace();
        }
    }*/

    @Override
    public List<ExcelIntentListVo> excelIntentList(IntentSearchVo dto) {
        List<ExcelIntentListVo> result = null;

        var query = queryFactory.select(
                        Projections.fields(ExcelIntentListVo.class,
                                qTbIntentMaster.seq
                                ,qTbIntentMaster.intentName
                                ,qTbBotCommonCode.codeName
//                                ,Expressions.stringTemplate("group_concat({0})", qTbIntentExample.exampleText).as("exampleText")
                        )
                ).from(qTbIntentMaster)
                .innerJoin(qTbBotCommonCode).on(qTbIntentMaster.category.eq(qTbBotCommonCode.minorCode)
                        .and(qTbBotCommonCode.oprMngCode.eq(dto.getOprMngCodeUpper())))
                /*.innerJoin(qTbIntentExample).on(qTbIntentMaster.seq.eq(qTbIntentExample.intentSeq))
                        .and(qTbIntentExample.useYn.eq("Y")))*/
                .where(qTbIntentMaster.useYn.eq("Y")
                        .and(qTbBotCommonCode.majorCode.eq("INTENT_GROUP")));
        if (dto.getOprMngCode() != null && !(dto.getOprMngCode().equals(""))) {
            query.where(qTbIntentMaster.oprMngCode.eq(dto.getOprMngCode()));
        }
        if (dto.getCategory() != null && !(dto.getCategory().equals(""))) {
            query.where(qTbIntentMaster.category.eq(dto.getCategory()));
        }
        if (dto.getIntentName() != null && !(dto.getIntentName().equals(""))) {
            query.where(qTbIntentMaster.intentName.contains(dto.getIntentName()));
        }
        query.groupBy(qTbIntentMaster.seq
                , qTbIntentMaster.intentName
                , qTbBotCommonCode.codeName
        );
        query.orderBy(qTbIntentMaster.intentName.asc());

        result = query.fetch();

        return result;

    }

}
