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


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Sequence;
import com.yeejoin.amos.knowledgebase.face.enumeration.DynamicsFunctional;
import com.yeejoin.amos.knowledgebase.face.feign.RemoteData;
import com.yeejoin.amos.knowledgebase.face.model.*;
import com.yeejoin.amos.knowledgebase.face.orm.dao.TagMapper;
import com.yeejoin.amos.knowledgebase.face.orm.entity.KnowledgeDocContent;
import com.yeejoin.amos.knowledgebase.face.orm.entity.KnowledgeTag;
import com.yeejoin.amos.knowledgebase.face.util.ConfigLoader;
import com.yeejoin.amos.knowledgebase.face.util.Constants;

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.StringUtil;
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 org.typroject.tyboot.core.restful.exception.instance.DataNotFound;
import org.typroject.tyboot.core.restful.exception.instance.RequestForbidden;

import java.util.*;


/**
 * <p>
 * 标签库 服务类
 * </p>
 *
 * @author 子杨
 * @since 2020-08-05
 */
@Component
public class TagService extends BaseService<KnowledgeTagModel, KnowledgeTag, TagMapper> {

    @Autowired
    private TagGroupService tagGroupService;
    @Autowired
    private InteractionCountService interactionCountService;
    @Autowired
    private TagGroupRefService tagGroupRefService;
    @Autowired
    private DynamicsValueService dynamicsValueService;
    @Autowired
    private TagInstanceService tagInstanceService;
    @Autowired
    private Sequence sequence;
    @Autowired
    private DocContentService docContentService;
    @Autowired
    private ConfigLoader configLoader;
    @Autowired
    private TagMapper tagMapper;

    /**
     * 统计方式-文档是否发布
     */
    public static final String QUOTE_TYPE_PUBLISHED = "PUBLISHED";

    /**
     * 创建标签
     *
     * @param model 标签信息
     * @return
     */
    @Transactional(rollbackFor = {Exception.class, BaseException.class})
    public KnowledgeTagModel createTag(KnowledgeTagModel model) {
        //判断标签名是否冲突
        if (!tagNameIsExist(model.getTagName(), null)) {
            throw new BadRequest("标签名称不可重复");
        }
        Long sequenceNbr = sequence.nextId();
        model.setSequenceNbr(sequenceNbr);
        model.setTagStatus(Constants.TAG_STATUS_ACTIVATE);
        model.setAgencyCode(RequestContext.getAgencyCode());
        model.setCreator(RequestContext.getExeUserId());
        //创建标签-分组关联关系
        tagGroupRefService.createGroupRefForTag(sequenceNbr, model.getTagGroup());
        //刷新动态字段值
        restoreDynamicsValues(sequenceNbr, model);

        return this.createWithModel(model);
    }

    /**
     * 修改标签
     *
     * @param model 标签信息
     * @return
     */
    @Transactional(rollbackFor = {Exception.class, BaseException.class})
    public KnowledgeTagModel updateTag(KnowledgeTagModel model) {
        KnowledgeTagModel oldTagModel = this.queryBySeq(model.getSequenceNbr());
        if (ValidationUtil.isEmpty(oldTagModel)) {
            throw new DataNotFound("找不到指定的标签");
        }
        //判断标签名是否冲突
        if (!tagNameIsExist(model.getTagName(), oldTagModel.getSequenceNbr())) {
            throw new BadRequest("标签名称不可重复");
        }
        //判断标签状态
        if (ValidationUtil.equals(oldTagModel.getTagStatus(), Constants.TAG_STATUS_ACTIVATE)) {
            throw new BadRequest("启用状态的标签不允许编辑");
        }
        Long sequenceNbr = oldTagModel.getSequenceNbr();
        //重建标签-分组关联关系
        tagGroupRefService.deleteRefsByTagSeq(sequenceNbr);
        tagGroupRefService.createGroupRefForTag(sequenceNbr, model.getTagGroup());
        //刷新动态字段值
        restoreDynamicsValues(sequenceNbr, model);
        Bean.copyExistPropertis(model, oldTagModel);
        return this.updateWithModel(oldTagModel);
    }

    private void restoreDynamicsValues(Long sequenceNbr, KnowledgeTagModel model) {
        if (ValidationUtil.equals(Constants.TAG_TYPE_VALUE, model.getTagType())) {
            Map<String, Object> tagValues = model.getTagValues();
            if (!ValidationUtil.isEmpty(tagValues)) {
                dynamicsValueService.saveValueList(tagValues, sequenceNbr,
                        DynamicsFunctional.VALUE_TAG_CONFIG,
                        Constants.APPKEY_ALL);
            }
        }
    }

    /**
     * 查询详情
     *
     * @param sequenceNbr 标签id
     * @return
     */
    public Map<String, Object> detailTag(Long sequenceNbr) {
        KnowledgeTagModel tagModel = this.queryBySeq(sequenceNbr);
        if (ValidationUtil.isEmpty(tagModel)) {
            throw new DataNotFound("找不到指定的标签");
        }
        //加入引用数量
        tagModel.setReferenceNumber(getAllReference(tagModel.getSequenceNbr()));
        //查询动态字段map
        tagAddDynamicsValues(tagModel);
        Map<String, Object> tagMap = Bean.BeantoMap(tagModel);
        //查询所属分组
        List<KnowledgeTagGroupRefModel> groupRefModels = tagGroupRefService.queryListByTagSeq(tagModel.getSequenceNbr());
        Set<Long> groupSeqSet = new HashSet<>();
        for (KnowledgeTagGroupRefModel groupRefModel : groupRefModels) {
            groupSeqSet.add(groupRefModel.getGroupSeq());
        }
        tagMap.put("tagGroup", groupSeqSet);
        //加入创建人姓名
        tagMap.put("creatorName", RemoteData.getUserRealNamById(tagModel.getCreator()));
        return tagMap;
    }


    /**
     * 条件查询，并以首字母作为key的Map结构封装数据
     *
     * @param groupSeq  标签分组id
     * @param tagName   标签名称
     * @param tagCode   标签代码
     * @param tagStatus 标签状态
     * @return Map<首字母String                                                                                                                                                                                                                                                               ,                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               列表List>
     */
    public Map<String, List<KnowledgeTagModel>> queryTagMap(Long groupSeq, String tagName, String tagCode, String tagStatus) {
        Map<String, List<KnowledgeTagModel>> resMap = new TreeMap<>();
        List<KnowledgeTag> tagList = queryTagListWithGroup(groupSeq, tagName, tagCode, tagStatus);
        for (KnowledgeTag tag : tagList) {
            KnowledgeTagModel tagModel = Bean.toModel(tag, new KnowledgeTagModel());
            //加入引用数量
//            tagModel.setReferenceNumber(getAllReference(tagModel.getSequenceNbr()));
            //被引用且已发布数量
            Integer num = tagMapper.queryCountByTagSeq(tagModel.getSequenceNbr(), QUOTE_TYPE_PUBLISHED);
            tagModel.setReferenceNumber(num);
            //获取拼音首字母
            String pinyin;
            try {
                String headWord = tagModel.getTagName().trim().substring(0, 1);
                pinyin = StringUtil.converterToFirstSpell(headWord).toUpperCase();
            } catch (Exception e) {
                System.out.println(e);
                pinyin = "#";
            }
            char initials = pinyin.charAt(0);
            if (initials < 65 || initials > 90) {
                initials = '#';
            }
            //将标签加入首字母对应的列表
            List<KnowledgeTagModel> list = resMap.get(String.valueOf(initials));
            if (ValidationUtil.isEmpty(list)) {
                list = new ArrayList<>();
                resMap.put(String.valueOf(initials), list);
            }
            list.add(tagModel);
        }
        return resMap;
    }

    /**
     * 条件查询--标签分组下及所有子分组下的标签
     */
    public List<KnowledgeTag> queryTagListWithGroup(Long groupSeq, String tagName, String tagCode, String tagStatus) {
        QueryWrapper<KnowledgeTag> wrapper = new QueryWrapper<>();
        if (!ValidationUtil.isEmpty(groupSeq)
                && !ValidationUtil.equals(groupSeq, TagGroupService.ROOT)) {
            KnowledgeTagGroupModel tagGroupModel = tagGroupService.queryBySeq(groupSeq);
            if (!ValidationUtil.isEmpty(tagGroupModel)) {
                List<Long> childGroupSequenceList = tagGroupService.getChildGroupSequenceList(tagGroupModel);
                List<Long> tagSeqList = tagGroupRefService.queryTagSeqListByGroupSeqList(childGroupSequenceList);
                if (!ValidationUtil.isEmpty(tagSeqList)) {
                    wrapper.in("sequence_nbr", tagSeqList);
                } else {
                    return Collections.EMPTY_LIST;
                }
            }
        }
        if (!ValidationUtil.isEmpty(tagName)) {
            wrapper.like("tag_name", tagName.trim());
        }
        if (!ValidationUtil.isEmpty(tagCode)) {
            wrapper.like("tag_code", tagCode.trim());
        }
        if (!ValidationUtil.isEmpty(tagStatus)) {
            wrapper.eq("tag_status", tagStatus);
        }
        return this.list(wrapper);
    }


    /**
     * 批量删除标签
     *
     * @param idList 标签id列表
     */
    @Transactional(rollbackFor = {Exception.class, BaseException.class})
    public List<Long> delete(List<Long> idList) {
        List<Long> resList = new ArrayList<>();
        List<KnowledgeTagModel> tagModels = this.queryByIds(idList);
        String tags = configLoader.getTags();
        List<Long> tagIdList = new ArrayList<>();
        if (!ValidationUtil.isEmpty(tags)) {
            tagIdList = StringUtil.String2LongList(tags);
        }
        for (KnowledgeTagModel tagModel : tagModels) {
            if (ValidationUtil.equals(tagModel.getTagStatus(), Constants.TAG_STATUS_ACTIVATE)) {
                throw new RequestForbidden("包含启用状态的标签，不允许删除");
            }
            if (tagIsQuoted(tagModel.getSequenceNbr())) {
                throw new RequestForbidden("包含被引用的标签，不允许删除");
            }
            if (configLoader.isTagWithName() && tagIdList.contains(tagModel.getSequenceNbr())) {
                throw new RequestForbidden("包含规则系统预定义的标签，不允许删除");
            }
            this.deleteBySeq(tagModel.getSequenceNbr());
            //删除分组关系
            tagGroupRefService.deleteRefsByTagSeq(tagModel.getSequenceNbr());
            resList.add(tagModel.getSequenceNbr());
        }
        return resList;
    }

    /**
     * 更新标签状态
     *
     * @param idList 标签id列表
     * @param active 启用/禁用
     * @return
     */
    @Transactional(rollbackFor = {Exception.class, BaseException.class})
    public List<KnowledgeTagModel> updateTagStatus(List<Long> idList, String active) {
        List<KnowledgeTagModel> tagModels = this.queryByIds(idList);
        for (KnowledgeTagModel tagModel : tagModels) {
            tagModel.setTagStatus(active);
            this.updateWithModel(tagModel);
        }
        return tagModels;
    }


    /**
     * 获取标签被所有文档引用数量
     *
     * @param sequenceNbr 标签id
     * @return 数量
     */
    public int getAllReference(Long sequenceNbr) {
        return getTagReferenceCount(sequenceNbr.toString(), InteractionCountService.QUOTE_TYPE_ALL);
    }

    public boolean tagIsQuoted(Long sequenceNbr) {
        int count = tagInstanceService.queryCountByTagSeq(sequenceNbr);
        boolean res = count > 0;
        if (res) {
            KnowledgeInteractionCountModel interactionCountModel = new KnowledgeInteractionCountModel();
            interactionCountModel.setEntityType(InteractionCountService.QUOTE_ENTITY_TAG);
            interactionCountModel.setOperateType(InteractionCountService.QUOTE_TYPE_ALL);
            interactionCountModel.setEntityId(sequenceNbr.toString());
            interactionCountModel.setOperateCount(count);
            interactionCountModel.setAgencyCode(configLoader.getAgencyCode());
            interactionCountService.createWithModel(interactionCountModel);
        }
        return res;
    }

//    /**
//     * 获取标签被已发布文档引用数量
//     *
//     * @param sequenceNbr 标签id
//     * @return 数量
//     */
//    public int getpublishedReference(Long sequenceNbr) {
//        return this.getTagReferenceCount(sequenceNbr.toString(), InteractionCountService.QUOTE_TYPE_PUBLISH);
//    }

    private int getTagReferenceCount(String sequenceNbr, String quoteType) {
        return interactionCountService.getOperateCount(quoteType, InteractionCountService.QUOTE_ENTITY_TAG, sequenceNbr);
    }

    /**
     * 标签名称是否可用
     *
     * @param tagName 标签名称
     * @return boolean
     */
    public boolean tagNameIsExist(String tagName, Long sequenceNbr) {
        QueryWrapper<KnowledgeTag> wrapper = new QueryWrapper<>();
        if (!ValidationUtil.isEmpty(sequenceNbr)) {
            wrapper.ne("sequence_nbr", sequenceNbr);
        }
        wrapper.eq("tag_name", tagName);
        return this.count(wrapper) == 0;
    }

//    /**
//     * 批量更新标签引用统计数
//     * @param tagIds 标签id列表
//     * @param isAll 全部引用还是发布引用
//     */
//    public void batchFlushTagCount(Collection<Long> tagIds, boolean isAll) {
//        if (ValidationUtil.isEmpty(tagIds)) {
//            return;
//        }
//        if (isAll) {
//            tagIds.forEach(tagId -> interactionCountService.flushOneTagCountAll(tagId));
//        }else {
//            List<KnowledgeDocContent> docContents = docContentService.queryIdListByStatus(DocContentService.DOC_STATUS_PUBLISHED);
//            Set targetSeqs = Bean.listToMap(docContents, "sequenceNbr", KnowledgeDocContent.class).keySet();
//            if (!ValidationUtil.isEmpty(targetSeqs)) {
//                tagIds.forEach(tagId -> interactionCountService.flushOneTagCountPublished(targetSeqs, tagId));
//            }
//        }
//    }

    public List<KnowledgeTagModel> queryByIds(@Condition(Operator.in) Collection<Long> sequenceNbr) {
        return this.queryForList(null, false, sequenceNbr);
    }

    /**
     * 获取被已发布文档引用数top15的标签
     *
     * @return
     */
    public List<KnowledgeTagModel> queryTopList(boolean isAll) {
        List<KnowledgeTagModel> res = new LinkedList<>();
        String operateType = isAll ? InteractionCountService.QUOTE_TYPE_ALL : InteractionCountService.QUOTE_TYPE_PUBLISH;
        List<KnowledgeInteractionCountModel> countModels = interactionCountService.queryTop(15, operateType, InteractionCountService.QUOTE_ENTITY_TAG, RequestContext.getAgencyCode());
        for (KnowledgeInteractionCountModel countModel : countModels) {
            if (countModel.getOperateCount() > 0) {
                KnowledgeTagModel tagModel = this.queryBySeq(Long.valueOf(countModel.getEntityId()));
                if (!ValidationUtil.isEmpty(tagModel)) {
                    res.add(tagModel);
                }
            } else {
                break;
            }
        }
        for (KnowledgeTagModel tagModel : res) {
            tagAddDynamicsValues(tagModel);
        }
        return res;
    }

    public List<KnowledgeTagModel> queryTagDetailList(String tagName) {
        List<KnowledgeTag> tagList = queryTagListWithGroup(null, tagName, null, Constants.TAG_STATUS_ACTIVATE);
        List<KnowledgeTagModel> res = new ArrayList<>();
        for (KnowledgeTag tag : tagList) {
            KnowledgeTagModel tagModel = new KnowledgeTagModel();
            Bean.copyExistPropertis(tag, tagModel);
            res.add(tagModel);
        }
        for (KnowledgeTagModel tagModel : res) {
            tagAddDynamicsValues(tagModel);
        }
        return res;
    }

    private void tagAddDynamicsValues(KnowledgeTagModel tagModel) {
        if (ValidationUtil.equals(Constants.TAG_TYPE_VALUE, tagModel.getTagType())) {
            List<KnowledgeDynamicsValueModel> valueModels = dynamicsValueService.queryByInstanceId(tagModel.getSequenceNbr());
            if (!ValidationUtil.isEmpty(valueModels)) {
                Map fieldsMap = Bean.listToMap(valueModels, "fieldName", KnowledgeDynamicsValueModel.class);
                tagModel.setTagValues(fieldsMap);
            }
        }
    }

//    public List<KnowledgeTagModel> queryByTagName(@Condition(Operator.like) String tagName, String tagStatus) {
//        return this.queryForList(null, false, tagName, tagStatus);
//    }

    /**
     * 查询标签关联的文档
     *
     * @param sequenceNbr 标签id
     * @return
     */
    public List queryRelatedDocList(Long sequenceNbr) {
        if (sequenceNbr == null) {
            throw new BadRequest("参数有误");
        }
        QueryWrapper<KnowledgeDocContent> wrapper = new QueryWrapper<KnowledgeDocContent>()
                .eq("DOC_STATUS", Constants.DOC_STATUS_PUBLISHED)
                .inSql("SEQUENCE_NBR", "SELECT DISTINCT TARGET_SEQ FROM knowledge_tag_instance WHERE TAG_SEQ = " + sequenceNbr);
        return docContentService.list(wrapper);
    }
}
