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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;

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.TreeBuilder;
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.RequestForbidden;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yeejoin.amos.knowledgebase.face.model.KnowledgeDocCategoryModel;
import com.yeejoin.amos.knowledgebase.face.model.MultipleNodeModel;
import com.yeejoin.amos.knowledgebase.face.orm.dao.DocCategoryMapper;
import com.yeejoin.amos.knowledgebase.face.orm.entity.KnowledgeDocCategory;
import com.yeejoin.amos.knowledgebase.face.orm.entity.KnowledgeTag;
import com.yeejoin.amos.knowledgebase.face.util.BaseUtil;
import com.yeejoin.amos.knowledgebase.face.util.Constants;
import com.yeejoin.amos.knowledgebase.face.util.TreeUtil;

/**
 * <p>
 * 知识库文档分类 服务类
 * </p>
 *
 * @author 子杨
 * @since 2020-08-05
 */
@Component
public class DocCategoryService extends BaseService<KnowledgeDocCategoryModel, KnowledgeDocCategory, DocCategoryMapper> {

    public static final Long ROOT = 0L;
    @Autowired
    private DocContentService docContentService;

    /**
     * 分页查询
     */
    public Page<KnowledgeDocCategoryModel> queryForKnowledgeDocCategoryPage(Page page, String agencyCode) {
        return this.queryForPage(page, null, false, agencyCode);
    }

    /**
     * 列表查询 示例
     */
    public List<KnowledgeDocCategoryModel> queryForKnowledgeDocCategoryList(Long parentId) {
        QueryWrapper<KnowledgeDocCategory> wrapper = new QueryWrapper<>();
        if (null != parentId) {
            wrapper.eq("PARENT_ID", parentId);
        }
//        wrapper.eq("AGENCY_CODE", RequestContext.getAgencyCode());
        List<KnowledgeDocCategory> list = this.list(wrapper);
        if (list.isEmpty()) {
            return Collections.emptyList();
        }
        return Bean.toModels(list, KnowledgeDocCategoryModel.class);
    }

    /**
     * @return java.util.Collection<com.yeejoin.amos.knowledgebase.face.model.KnowledgeDocCategoryModel>
     * @author 吴俊凯
     * @description 查询知识库文档分类树结构
     * @Param [agencyCode]
     **/
    public Collection<KnowledgeDocCategoryModel> queryDocCategoryTree(String agencyCode, Long root) {
        List<KnowledgeDocCategoryModel> list = this.queryForKnowledgeDocCategoryList(null);

        Map<Object, KnowledgeDocCategoryModel> map = Bean.listToMap(list, "sequenceNbr", KnowledgeDocCategoryModel.class);

        SortedSet<KnowledgeDocCategoryModel> completeList = new TreeSet<>();
        for (KnowledgeDocCategoryModel model : list) {
            completeList.addAll(buildWithParent(model, map));
        }
        return TreeBuilder.buildByRecursive(completeList, root);
    }

    /**
     * @return java.util.List<com.yeejoin.amos.knowledgebase.face.model.KnowledgeDocCategoryModel>
     * @author 吴俊凯
     * @description 构建不完整的树
     * @Param [groupModel, map]
     **/
    private List<KnowledgeDocCategoryModel> buildWithParent(KnowledgeDocCategoryModel groupModel, Map<Object, KnowledgeDocCategoryModel> map) {

        List<KnowledgeDocCategoryModel> completeList = new ArrayList<>();
        completeList.add(groupModel);

        if (groupModel.getParentId().equals(ROOT)) {
            completeList.add(groupModel);
            return completeList;
        }

        KnowledgeDocCategoryModel parent = map.get(groupModel.getParentId());
        if (ValidationUtil.isEmpty(parent)) {
            parent = this.queryBySeq(groupModel.getParentId());

            if (ValidationUtil.isEmpty(parent)) {
                return completeList;
            }
        }
        completeList.add(parent);
        completeList.addAll(this.buildWithParent(parent, map));
        return completeList;
    }

    /**
     * @return java.util.List<java.lang.Long>
     * @author 杨博超
     * @description 删除分类
     * @Param [ids]
     **/
    @Transactional(rollbackFor = {Exception.class, BaseException.class})
    public List<Long> deleteDocCategory(String ids) {
        List<Long> seqs = StringUtil.String2LongList(ids);
        for (Long seq : seqs) {
            KnowledgeDocCategoryModel DocCategoryModel = this.queryBySeq(seq);
            //所有子分类
            List<Long> childGroupSequenceList = getChildGroupSequenceList(DocCategoryModel);
            List<Long> existTags = this.queryDocListWithCategory(seq, null, null, null);
            if (!ValidationUtil.isEmpty(existTags)) {
                throw new RequestForbidden("分类下存在文档，不允许删除！");
            }
            this.deleteBatchSeq(childGroupSequenceList);
        }
        return seqs;
    }

    /**
     * 条件查询--标签分组下及所有子分组下的标签
     */
    public List<Long> queryDocListWithCategory(Long groupSeq, String tagName, String tagCode, String tagStatus) {
        QueryWrapper<KnowledgeTag> wrapper = new QueryWrapper<>();
        List<Long> tagSeqList = null;
        if (!ValidationUtil.isEmpty(groupSeq)
                && !ValidationUtil.equals(groupSeq, TagGroupService.ROOT)) {
            KnowledgeDocCategoryModel DocCategoryModel = this.queryBySeq(groupSeq);
            if (!ValidationUtil.isEmpty(DocCategoryModel)) {
                List<Long> childGroupSequenceList = getChildGroupSequenceList(DocCategoryModel);
                tagSeqList = docContentService.queryContentSeqListByCategorySeqList(childGroupSequenceList);
//                                if (!ValidationUtil.isEmpty(tagSeqList)) {
//                                        wrapper.in("sequence_nbr", tagSeqList);
//                                } else {
//                                        return Collections.EMPTY_LIST;
//                                }
            }
        }
        return tagSeqList;
    }

    /**
     * 获取标签分组的所有子分组id
     *
     * @param parentTagGroupModel
     * @return
     */
    public List<Long> getChildGroupSequenceList(KnowledgeDocCategoryModel parentTagGroupModel) {
        List<Long> sequenceList = new ArrayList<>();
        List<KnowledgeDocCategoryModel> childList = new ArrayList<>();
        this.getAllChildList(parentTagGroupModel, childList);
        for (KnowledgeDocCategoryModel tagGroupModel : childList) {
            sequenceList.add(tagGroupModel.getSequenceNbr());
        }
        return sequenceList;
    }

    private void getAllChildList(KnowledgeDocCategoryModel currentTagGroupModel, List<KnowledgeDocCategoryModel> resList) {
        if (null == currentTagGroupModel) {
            return;
        }
        Long parentId = currentTagGroupModel.getSequenceNbr();
        List<KnowledgeDocCategoryModel> childList = queryByParentId(parentId);
        if (!childList.isEmpty()) {
            for (KnowledgeDocCategoryModel tagGroupModel : childList) {
                this.getAllChildList(tagGroupModel, resList);
            }
        }
        resList.add(currentTagGroupModel);
    }

    private List<KnowledgeDocCategoryModel> queryByParentId(Long parentId) {
        return this.queryForList("", false, parentId);
    }

    public Collection queryDocCategoryTreeExtra(String agencyCode, Long root, Boolean onlyPublish) {
        KnowledgeDocCategoryModel rootCategory = null;
        if (root != null && !ROOT.equals(root)) {
            rootCategory = this.queryBySeq(root);
        }
        Collection<KnowledgeDocCategoryModel> categoryTree = this.queryDocCategoryTree(agencyCode, root);
        if (null != rootCategory) {
            rootCategory.setChildren(categoryTree);
            categoryTree = Arrays.asList(rootCategory);
        }
        if (!categoryTree.isEmpty()) {
            List<KnowledgeDocCategoryModel> allChildren = TreeUtil.getAllChildren(categoryTree);
            if (!allChildren.isEmpty()) {
                List<Long> directoryIds = BaseUtil.getModelIds(allChildren);
                List<MultipleNodeModel> multipleNodeModels = this.baseMapper.queryDocAndCategoryTree(directoryIds, onlyPublish ? Constants.DOC_STATUS_PUBLISHED : null);
                return TreeBuilder.buildByRecursive(multipleNodeModels, null == rootCategory ? root : rootCategory.getParentId());
            }
        }
        return Collections.emptyList();
    }

    public KnowledgeDocCategoryModel createOne(KnowledgeDocCategoryModel model) {
        if (ValidationUtil.isEmpty(model) || ValidationUtil.isEmpty(model.getCategoryName())) {
            throw new BadRequest("数据格式错误");
        }
        if (model.getParentId() == null) {
            model.setParentId(ROOT);
        }
        model.setAgencyCode(RequestContext.getAgencyCode());
        KnowledgeDocCategoryModel oldModel = this.queryByNameAndParent(model.getCategoryName(), model.getParentId());
        if (!ValidationUtil.isEmpty(oldModel)) {
            throw new BadRequest("同级目录下已存在此分类名称.");
        }
        this.createWithModel(model);
        return null;
    }

    public KnowledgeDocCategoryModel updateOne(KnowledgeDocCategoryModel model) {
        if (ValidationUtil.isEmpty(model) || ValidationUtil.isEmpty(model.getCategoryName())) {
            throw new BadRequest("数据格式错误");
        }
        KnowledgeDocCategoryModel oldModel = this.queryBySeq(model.getSequenceNbr());
        if (ValidationUtil.isEmpty(oldModel)) {
            throw new BadRequest("原数据不存在");
        }
        if (!model.getCategoryName().equals(oldModel.getCategoryName())) {
            KnowledgeDocCategoryModel targetModel = this.queryByNameAndParent(model.getCategoryName(), model.getParentId());
            if (!ValidationUtil.isEmpty(targetModel)) {
                throw new BadRequest("同级目录下已存在此分类名称.");
            }
        }
        Bean.copyExistPropertis(model, oldModel);
        return this.updateWithModel(oldModel);
    }

    private KnowledgeDocCategoryModel queryByNameAndParent(@Condition(Operator.eq) String categoryName, @Condition(Operator.eq) Long parentId) {
        List<KnowledgeDocCategoryModel> categoryModelList = this.queryForList(null, true, categoryName, parentId);
        return categoryModelList.isEmpty() ? null : categoryModelList.get(0);
    }
}
