package com.yeejoin.amos.knowledgebase.face.service;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yeejoin.amos.knowledgebase.face.enumeration.DynamicsFunctional;
import com.yeejoin.amos.knowledgebase.face.enumeration.KnowledgeRoleName;
import com.yeejoin.amos.knowledgebase.face.enumeration.OptionDataType;
import com.yeejoin.amos.knowledgebase.face.feign.DataFillter;
import com.yeejoin.amos.knowledgebase.face.model.KnowledgeDynamicsOptionModel;
import com.yeejoin.amos.knowledgebase.face.model.KnowledgeDynamicsValueModel;
import com.yeejoin.amos.knowledgebase.face.orm.dao.DynamicsValueMapper;
import com.yeejoin.amos.knowledgebase.face.orm.entity.KnowledgeDynamicsValue;
import com.yeejoin.amos.knowledgebase.face.util.Constants;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.typroject.tyboot.core.foundation.context.RequestContext;
import org.typroject.tyboot.core.foundation.exception.BaseException;
import org.typroject.tyboot.core.foundation.utils.Bean;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;
import org.typroject.tyboot.core.rdbms.annotation.Condition;
import org.typroject.tyboot.core.rdbms.annotation.Operator;
import org.typroject.tyboot.core.rdbms.service.BaseService;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;

import java.util.*;


/**
 * <p>
 * 知识库系统动态选项配置的实例值 服务类
 * </p>
 *
 * @author 子杨
 * @since 2020-08-05
 */
@Component
public class DynamicsValueService extends BaseService<KnowledgeDynamicsValueModel, KnowledgeDynamicsValue, DynamicsValueMapper> implements DataFillter {

    @Autowired
    private DynamicsOptionService dynamicsOptionService;


    /**
     * @return java.util.List<com.yeejoin.amos.knowledgebase.face.model.KnowledgeDynamicsValueModel>
     * @author 杨博超
     * @description 创建动态字段的值
     * @Param [valueOfMap, instanceId]
     **/
    @Transactional(rollbackFor = {Exception.class, BaseException.class})
    public List<KnowledgeDynamicsValueModel> saveValueList(Map<String, Object> valueMap, Long instanceId, DynamicsFunctional functional, String appKey) {

        List<KnowledgeDynamicsValueModel> returnList = new ArrayList<>();

        //删除已经存在的
        deleteByInstanceId(instanceId);

        if (ValidationUtil.isEmpty(valueMap)) {
            return returnList;
        }
        List<KnowledgeDynamicsOptionModel> optionModels = dynamicsOptionService.queryByFunctional(appKey, functional.name());

        for (KnowledgeDynamicsOptionModel optionModel : optionModels) {

            Object value = valueMap.get(optionModel.getFieldName());
            if (ValidationUtil.isEmpty(value)) {
                continue;
            }

            KnowledgeDynamicsValueModel valueModel = new KnowledgeDynamicsValueModel();

            valueModel.setFieldValue(String.valueOf(value));
            valueModel.setFieldName(optionModel.getFieldName());
            valueModel.setDataType(optionModel.getDataType());
            valueModel.setAgencyCode(RequestContext.getAgencyCode());
            valueModel.setFieldLabel(optionModel.getFieldLabel());
            valueModel.setGroupSeq(optionModel.getGroupSeq());
            valueModel.setQueryStrategy(optionModel.getQueryStrategy());
            valueModel.setInstanceId(instanceId);
            valueModel.setOptionSeq(optionModel.getSequenceNbr());

            this.createWithModel(valueModel);
            returnList.add(valueModel);
        }
        return returnList;
    }


    public Set<Long> intersection(String agencyCode, Long groupSeq, Map<String, String[]> paramMap) {
        Set<Long> set = new HashSet<>();
        List<KnowledgeDynamicsValue> entities;
        if (ValidationUtil.isEmpty(paramMap)) {
            QueryWrapper<KnowledgeDynamicsValue> wrapper = this.asymbleWrapper(agencyCode, groupSeq, paramMap);
            wrapper.select("INSTANCE_ID");
            entities = this.list(wrapper);
            if (!ValidationUtil.isEmpty(entities)) {
                Map map = Bean.listToMap(entities, "instanceId", KnowledgeDynamicsValue.class);
                set = map.keySet();
            }
        } else {
            List<Set<Long>> setList = new ArrayList<>();
            for (String key : paramMap.keySet()) {
                Map<String, String[]> newParams = new HashMap<>();
                newParams.put(key, paramMap.get(key));
                QueryWrapper<KnowledgeDynamicsValue> wrapper = this.asymbleWrapper(agencyCode, groupSeq, newParams);
                wrapper.select("INSTANCE_ID");
                entities = this.list(wrapper);
                if (!ValidationUtil.isEmpty(entities)) {
                    Map map = Bean.listToMap(entities, "instanceId", KnowledgeDynamicsValue.class);
                    Set<Long> newSet = map.keySet();
                    setList.add(newSet);
                }
            }
            set = new HashSet<>(intersection(setList));
        }
        return set;
    }


    protected Collection intersection(List<Set<Long>> setList) {
        Collection list = new ArrayList();
        if (!ValidationUtil.isEmpty(setList)) {
            list = new ArrayList(setList.get(0));
            for (int i = 0; i < setList.size(); i++) {
                if (i + 1 >= setList.size()) {
                    break;
                }
                list = CollectionUtils.intersection(list, setList.get(i + 1));
            }
        }
        return list;
    }


    @Override
    public Map<String, Object> assembleParams(List<String> roleNameList, String orgCode) {
        Map<String, Object> dataPrivilegemap = new HashMap<>();
        if (!ValidationUtil.isEmpty(roleNameList)) {

            Set<String> auditStatusSet = new HashSet<>();
            Set<String> docStatusSet = new HashSet<>();
            for (String roleName : roleNameList) {
                KnowledgeRoleName knowledgeRoleName = KnowledgeRoleName.getInstance(roleName);
                if (ValidationUtil.isEmpty(knowledgeRoleName)) {
                    continue;
                }
                switch (knowledgeRoleName) {
                    case AUDITOR:
                        auditStatusSet.add(Constants.DOC_AUDIT_STATUS_PASSED);
                        auditStatusSet.add(Constants.DOC_AUDIT_STATUS_SUBMITTED);
                        dataPrivilegemap.put(DataFillter.orgCode, orgCode);
                        dataPrivilegemap.put(auditStatus, auditStatusSet.toArray(new String[auditStatusSet.size()]));
                        break;
                    case INPUTER:
                        dataPrivilegemap.put(DataFillter.userId, RequestContext.getExeUserId());
                        break;
                    case TAG_MANAGER:
                        dataPrivilegemap.put(DataFillter.noData, true);
                        break;
                    case VIEWER:
                        auditStatusSet.add(Constants.DOC_AUDIT_STATUS_PASSED);
                        docStatusSet.add(Constants.DOC_STATUS_PUBLISHED);
                        dataPrivilegemap.put(docStatus, docStatusSet.toArray(new String[docStatusSet.size()]));
                        dataPrivilegemap.put(auditStatus, auditStatusSet.toArray(new String[auditStatusSet.size()]));
                        break;
                    default:
                        throw new BadRequest("错误的用户角色.");
                }
                break;// TODO  多角色处理
            }
        }


        return dataPrivilegemap;
    }


    /*protected Set<Long> withCollection(Set<Long> instanceIds, boolean filterByCollection, List<Long> myFavorites) {
        //与我的收藏取交集
        if (filterByCollection) {
            if (ValidationUtil.isEmpty(myFavorites)) {
                instanceIds.clear();
            } else {
                Iterator<Long> iterator = instanceIds.iterator();
                while (iterator.hasNext()) {
                    if (!myFavorites.contains(iterator.next())) {
                        iterator.remove();
                    }
                }
            }
        }

        return instanceIds;
    }
*/

    /**
     * @return com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<com.yeejoin.amos.knowledgebase.face.orm.entity.KnowledgeDynamicsValue>
     * @author 杨博超
     * @description 组装查询条件
     * @Param [agencyCode, groupCode, paramMap]
     **/
    private QueryWrapper<KnowledgeDynamicsValue> asymbleWrapper(String agencyCode, Long groupSeq, Map<String, String[]> paramMap) {
        QueryWrapper<KnowledgeDynamicsValue> wrapper = new QueryWrapper<>();
        wrapper.eq("AGENCY_CODE", agencyCode);
        wrapper.eq("GROUP_SEQ", groupSeq);
        if (!ValidationUtil.isEmpty(paramMap)) {
            wrapper.and(innerWrapper -> {
                List<KnowledgeDynamicsValueModel> list = queryByGroup(agencyCode, groupSeq);
                if (!ValidationUtil.isEmpty(list)) {
                    for (int i = 0, count = 0; i < list.size(); i++) {
                        KnowledgeDynamicsValueModel valueModel = list.get(i);
                        if (paramMap.keySet().contains(valueModel.getFieldName())) {
                            asymbleWrapper(innerWrapper, valueModel, paramMap, count);
                            count++;
                        }
                    }
                }
            });
        }

        return wrapper;
    }


    /**
     * @return com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<com.yeejoin.amos.knowledgebase.face.orm.entity.KnowledgeDynamicsValue>
     * @author 杨博超
     * @description 组装查询条件
     * @Param [wrapper, valueModel, paramMap, i]
     **/
    protected QueryWrapper<KnowledgeDynamicsValue> asymbleWrapper(QueryWrapper<KnowledgeDynamicsValue> wrapper, KnowledgeDynamicsValueModel valueModel, Map<String, String[]> paramMap, int count) {
        OptionDataType dataType = OptionDataType.valueOf(valueModel.getDataType());
        String fieldName = valueModel.getFieldName();
        String columName = "FIELD_VALUE";
        switch (dataType) {
            case Enum:
            case String:
                break;
            case Double:
                columName = "CONVERT(" + columName + ",DECIMAL)";
            case Integer:
                columName = "CONVERT(" + columName + ",SIGNED)";
                break;
            case datetime:
                columName = "STR_TO_DATE(" + columName + ", '%Y-%m-%d %H:%i:%s')";
                break;
            case Date:
                columName = "STR_TO_DATE(" + columName + ", '%Y-%m-%d')";
                break;
            default:
                throw new RuntimeException("错误的数据类型");
        }
        wrapper = this.asymbleWrapper(wrapper, fieldName, columName, valueModel.getQueryStrategy(), paramMap, count);
        return wrapper;
    }


    private QueryWrapper<KnowledgeDynamicsValue> asymbleWrapper(QueryWrapper<KnowledgeDynamicsValue> wrapper, String fieldName, String columName, String queryStrategy, Map<String, String[]> paramMap, int count) {
        String fieldValue = paramMap.get(fieldName)[0];
        Operator operator = Operator.valueOf(queryStrategy);

        if (count == 0) {
            switch (operator) {
                case eq:

                    wrapper.eq(columName, fieldValue)
                            .eq("FIELD_NAME", fieldName);
                    break;
                case like:
                    wrapper.like(columName, fieldValue)
                            .eq("FIELD_NAME", fieldName);
                    break;
                case between:
                    String fieldValueArr[] = paramMap.get(fieldName);
                    if (!ValidationUtil.isEmpty(fieldValueArr[0]))
                        wrapper.ge(columName, fieldValueArr[0]).eq("FIELD_NAME", fieldName);

                    if (!ValidationUtil.isEmpty(fieldValueArr[1]))
                        wrapper.le(columName, fieldValueArr[1]).eq("FIELD_NAME", fieldName);
                    //wrapper.between(columName, fieldValueArr[0], fieldValueArr[1])
                    //  .eq("FIELD_NAME", fieldName);
                default:
                    throw new RuntimeException("动态字段查询方式有误.");

            }
        } else {
            switch (operator) {
                case eq:
                    wrapper.or((i) -> i.eq(columName, fieldValue)
                            .eq("FIELD_NAME", fieldName));
                    break;
                case like:
                    wrapper.or((i) -> i.like(columName, fieldValue)
                            .eq("FIELD_NAME", fieldName));
                    break;
                case between:
                    String fieldValueArr[] = paramMap.get(fieldName);
                    wrapper.or((i) -> i.between(columName, fieldValueArr[0], fieldValueArr[1])
                            .eq("FIELD_NAME", fieldName));
                default:
                    throw new RuntimeException("动态字段查询方式有误.");

            }
        }

        return wrapper;
    }


    /**
     * @return java.util.List<com.yeejoin.amos.knowledgebase.face.model.KnowledgeDynamicsValueModel>
     * @author 杨博超
     * @description 根据分组编号查询动态字段值列表
     * @Param [agencyCode, groupCode]
     **/
    public List<KnowledgeDynamicsValueModel> queryByGroup(String agencyCode, Long groupSeq) {
        return this.queryForListWithCache("", false, agencyCode, groupSeq);
    }


   /* public List<KnowledgeDynamicsValueModel> queryByGroupWithoutAgency(Long groupSeq) {
        return this.queryForListWithCache("", false, groupSeq);
    }*/


    /**
     * @return java.util.List<com.yeejoin.amos.knowledgebase.face.model.KnowledgeDynamicsValueModel>
     * @author 杨博超
     * @description 根据实例id查询动态字值段列表
     * @Param [instanceId]
     **/
    public List<KnowledgeDynamicsValueModel> queryByInstanceId(Long instanceId) {
//        return this.queryForListWithCache("", false, instanceId);
        return this.queryForList("", false, instanceId);
    }


    public List<KnowledgeDynamicsValueModel> queryByOptionSeq(Long optionSeq) {
        return this.queryForTopList(1, "", false, optionSeq);
    }


    /**
     * 根据实例id删除动态值列表
     *
     * @param instanceId 实例id
     * @return
     */
    @Transactional
    public List<Long> deleteByInstanceId(Long instanceId) {
        List<Long> deleteList = new ArrayList<>();
        List<KnowledgeDynamicsValueModel> existValues = queryByInstanceId(instanceId);
        if (!ValidationUtil.isEmpty(existValues)) {
            for (KnowledgeDynamicsValueModel existValue : existValues) {
                this.deleteBySeq(existValue.getSequenceNbr());
                deleteList.add(existValue.getSequenceNbr());
            }
        }
        return deleteList;
    }


    public List<KnowledgeDynamicsValueModel> queryFieldValueByIds(@Condition(Operator.in) Collection<String> instanceId, String fieldName) {
        return this.queryForList("", false, instanceId, fieldName);
    }

    public List<KnowledgeDynamicsValueModel> queryByInstanceIds(@Condition(Operator.in) Collection<Long> instanceId) {
        return this.queryForList("", false, instanceId);
    }
}
