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

import com.icomsys.main_vm.biz.common.system.vo.SystemBotUserReq;
import com.icomsys.main_vm.biz.common.system.vo.SystemBotUserRes;
import com.icomsys.main_vm.biz.common.system.vo.SystemServiceAuthGroupUserSearchReq;
import com.icomsys.main_vm.biz.common.system.vo.SystemServiceAuthGroupUserSearchRes;
import com.icomsys.main_vm.biz.test.controller.TestVoUser;
import com.icomsys.main_vm.common.code.enumresource.RoleResource;
import com.icomsys.main_vm.db.jpa.entity.system.*;
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 com.querydsl.jpa.sql.JPASQLQuery;
import com.querydsl.sql.SQLExpressions;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.Aspect;

import java.util.ArrayList;
import java.util.List;

@Aspect
@Slf4j
@RequiredArgsConstructor
public class TbBotUserRepoDslImpl implements TbBotUserRepoDsl {

    private final JPAQueryFactory queryFactory;
    private QTbBotUser qTbBotUser = QTbBotUser.tbBotUser;
    private QTbUserCust qTbUserCust = QTbUserCust.tbUserCust;
    private QTbServiceGrouop qTbServiceGrouop = QTbServiceGrouop.tbServiceGrouop;
    private QTbIcsCustInfo qTbIcsCustInfo = QTbIcsCustInfo.tbIcsCustInfo;
    private QTbUserAuthGroup qTbUserAuthGroup = QTbUserAuthGroup.tbUserAuthGroup;

    @Override
    public QueryResults<SystemBotUserRes> SystemUserList(SystemBotUserReq dto, String role) {
        QueryResults<SystemBotUserRes> result = null;

        if (dto.getUserVo().getRoleVal().equals(RoleResource.SYSTEMADMIN.getName())) {
            return result = queryFactory.select(
                            Projections.fields(
                                    SystemBotUserRes.class,
                                    qTbBotUser.custCode,
                                    qTbIcsCustInfo.custName,
                                    qTbBotUser.userSeq,
                                    qTbBotUser.userId,
                                    qTbBotUser.userName,
                                    qTbBotUser.eMail,
                                    qTbBotUser.mobileNo,
                                    qTbBotUser.useYn,
                                    qTbBotUser.registDate
                            )
                    ).from(qTbBotUser)
                    .innerJoin(qTbIcsCustInfo).on(qTbIcsCustInfo.custCode.eq(qTbBotUser.custCode))
                    .where(
//                            qTbServiceGrouop.serviceGroupUpper.eq(dto.getUserVo().getLastUseServiceGroup())
                            qTbCustCodeeq(dto)
                            , qTbBotUsersearcheq(dto)
                            , qTbBotUser.roleVal.eq(RoleResource.USERADMIN.getName()).or(qTbBotUser.roleVal.eq(RoleResource.USER.getName()))
                    )

                    .limit(dto.getSize())
                    .offset(dto.getPage() * dto.getSize())
                    .orderBy(qTbBotUser.registDate.desc())
                    .groupBy(
                            qTbBotUser.custCode,
                            qTbIcsCustInfo.custName,
                            qTbBotUser.userSeq,
                            qTbBotUser.userId,
                            qTbBotUser.userName,
                            qTbBotUser.eMail,
                            qTbBotUser.mobileNo,
                            qTbBotUser.useYn,
                            qTbBotUser.registDate
                    )
                    .fetchResults();
        } else {
            return result = queryFactory.select(
                            Projections.fields(
                                    SystemBotUserRes.class,
                                    qTbBotUser.custCode,
                                    qTbIcsCustInfo.custName,
//                                        qTbServiceGrouop.serviceGroup,
//                                        qTbServiceGrouop.serviceGroupName,
                                    qTbBotUser.userSeq,
                                    qTbBotUser.userId,
                                    qTbBotUser.userName,
                                    qTbBotUser.eMail,
                                    qTbBotUser.mobileNo,
                                    qTbBotUser.useYn,
                                    qTbBotUser.registDate
                            )
                    ).from(qTbBotUser)
                    .innerJoin(qTbIcsCustInfo).on(qTbBotUser.custCode.eq(qTbIcsCustInfo.custCode))
                    .innerJoin(qTbServiceGrouop).on(qTbBotUser.lastUseServiceGroup.eq(qTbServiceGrouop.serviceGroupUpper))
                    /*
                                          .from(qTbUserCust)
                                          //내가사용할 수 있는 UserCust의 서비스그룹
                                          .innerJoin(qTbServiceGrouop).on(qTbUserCust.serviceGroup.eq(qTbServiceGrouop.serviceGroup))
                                          .innerJoin(qTbIcsCustInfo).on(qTbUserCust.custCode.eq(qTbIcsCustInfo.custCode))
                                          .innerJoin(qTbBotUser).on(qTbUserCust.userSeq.eq(qTbBotUser.userSeq))
                                                               .where(qTbUserCust.userSeq.eq(dto.getUserVo().getUserSeq())
                            , qTbUserCust.serviceGroup.eq(qTbServiceGrouop.serviceGroup)
                            , qTbServiceGrouop.serviceGroupUpper.eq(dto.getUserVo().getLastUseServiceGroup())
                            , qTbServiceGrouopeq(dto)
                            , qTbBotUsersearcheq(dto)
                             */
                    .where(
                            qTbServiceGrouop.serviceGroupUpper.eq(dto.getUserVo().getLastUseServiceGroup())
                            , qTbCustCodeeq(dto)
                            , qTbBotUsersearcheq(dto)
                            , qTbBotUser.roleVal.eq(RoleResource.USERADMIN.getName()).or(qTbBotUser.roleVal.eq(RoleResource.USER.getName()))
                    )
                    .limit(dto.getSize())
                    .offset(dto.getPage() * dto.getSize())
                    .orderBy(qTbBotUser.registDate.desc())
                    .groupBy(
                            qTbBotUser.custCode,
                            qTbIcsCustInfo.custName,
                            qTbBotUser.userSeq,
                            qTbBotUser.userId,
                            qTbBotUser.userName,
                            qTbBotUser.eMail,
                            qTbBotUser.mobileNo,
                            qTbBotUser.useYn,
                            qTbBotUser.registDate
                    )
                    .fetchResults();
        }
    }

    private BooleanExpression qTbCustCodeeq(SystemBotUserReq dto) {
        return dto.getCustCode().equals("ALL") ?
                null : qTbIcsCustInfo.custCode.eq(dto.getCustCode());
    }

    private BooleanExpression qTbBotUsersearcheq(SystemBotUserReq dto) {
        if (dto.getCodeText() == null || dto.getCodeText().equals("")) {
            return null;
        } else {
            if (dto.getCodeType().equals("ALL")) {
                return qTbBotUser.userId.upper().contains(dto.getCodeText().toUpperCase()).or(qTbBotUser.userName.upper().contains(dto.getCodeText().toUpperCase()));
            } else if (dto.getCodeType().equals("userId")) {
                return qTbBotUser.userId.upper().contains(dto.getCodeText().toUpperCase());
            } else if (dto.getCodeType().equals("userName")) {
                return qTbBotUser.userName.upper().contains(dto.getCodeText().toUpperCase());
            } else {
                return null;
            }
        }
    }

    public List<SystemBotUserRes> AuthGroupUserList(Long authGroupSeq) {
        List<SystemBotUserRes> result =
                queryFactory.select(
                                Projections.fields(
                                        SystemBotUserRes.class,
                                        qTbBotUser.custCode,
                                        qTbIcsCustInfo.custName,
//                                        qTbServiceGrouop.serviceGroup,
//                                        qTbServiceGrouop.serviceGroupName,
                                        qTbBotUser.userSeq,
                                        qTbBotUser.userId,
                                        qTbBotUser.userName,
                                        qTbBotUser.eMail,
                                        qTbBotUser.mobileNo,
                                        qTbBotUser.useYn,
                                        qTbBotUser.registDate
                                )
                        )
                        .from(qTbUserAuthGroup)
                        .innerJoin(qTbBotUser).on(qTbBotUser.userSeq.eq(qTbUserAuthGroup.userSeq))
//                        .innerJoin(qTbServiceGrouop).on(qTbServiceGrouop.serviceGroup.eq(qTbUserAuthGroup.serviceGroup))
                        .innerJoin(qTbIcsCustInfo).on(qTbIcsCustInfo.custCode.eq(qTbUserAuthGroup.custCode))
                        .where(qTbUserAuthGroup.authGroupSeq.eq(authGroupSeq))
                        .groupBy(qTbBotUser.custCode,
                                qTbIcsCustInfo.custName,
//                                qTbServiceGrouop.serviceGroup,
//                                qTbServiceGrouop.serviceGroupName,
                                qTbBotUser.userSeq,
                                qTbBotUser.userId,
                                qTbBotUser.userName,
                                qTbBotUser.eMail,
                                qTbBotUser.mobileNo,
                                qTbBotUser.useYn,
                                qTbBotUser.registDate)
                        .fetch();
        return result;
    }

//    @Override
//    public List<TestVoUser> testConCat() {
//        return queryFactory.select(
//                        Projections.fields(
//                                TestVoUser.class,
//                                Expressions.stringTemplate("group_concat( {0} ) ",
//                                        qTbUserAuthGroup.serviceGroup
////                                        ExpressionUtils.distinctList(JPAExpressions.select(qTbUserAuthGroup.serviceGroup)
////                                        .from(qTbUserAuthGroup)
////                                        .where(qTbUserAuthGroup.userSeq.eq(qTbBotUser.userSeq))
////                                        .groupBy(qTbUserAuthGroup.serviceGroup)))
//                                ).as("serviceGroup")
//                        )
//                )
//                .from(qTbBotUser)
//                .innerJoin(qTbUserAuthGroup).on(qTbUserAuthGroup.userSeq.eq(qTbBotUser.userSeq))
//                .fetch();
//    }

//    private String eqTbIntentMasterIntentName(List<String> names) {
//        return names != null ? Expressions.allOf(
//                names.stream().map(this::isintentName)
//                        .toArray(BooleanExpression[]::new)) : null;
//    }

    public List<SystemServiceAuthGroupUserSearchRes> GroupAuthUpdateDataUserSearch(SystemServiceAuthGroupUserSearchReq dto) {

        List<SystemServiceAuthGroupUserSearchRes> result = new ArrayList<>();

        result = queryFactory.select(
                        Projections.fields(
                                SystemServiceAuthGroupUserSearchRes.class,
                                qTbBotUser.userSeq,
                                qTbBotUser.custCode,
                                qTbBotUser.lastUseServiceGroup,
                                qTbBotUser.roleVal,
                                qTbBotUser.userId,
                                qTbBotUser.userName,
                                qTbBotUser.eMail,
                                qTbBotUser.mobileNo,
                                qTbBotUser.useYn
                                )
                )
                .from(qTbBotUser)
                .where(userTextEq(dto.getUserSearchText()))
                .limit(30)
                .groupBy(
                        qTbBotUser.userSeq,
                        qTbBotUser.custCode,
                        qTbBotUser.lastUseServiceGroup,
                        qTbBotUser.roleVal,
                        qTbBotUser.userId,
                        qTbBotUser.userName,
                        qTbBotUser.eMail,
                        qTbBotUser.mobileNo,
                        qTbBotUser.useYn
                )
                .fetchResults()
                .getResults();
        return result;
    }

    private BooleanExpression userTextEq(String s){
        if(s == null){
            return null;
        }
        else {
            return qTbBotUser.userId.toUpperCase().contains(s.toUpperCase()).or(qTbBotUser.userName.toUpperCase().contains(s.toUpperCase()));
        }
    }

}
