package com.hai.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.hai.common.exception.ErrorCode;
import com.hai.common.exception.ErrorHelp;
import com.hai.common.exception.SysCode;
import com.hai.dao.CmsCategoryMapper;
import com.hai.entity.CmsCategory;
import com.hai.entity.CmsCategoryExample;
import com.hai.model.CmsCategoryTreeModel;
import com.hai.service.CmsCategoryRoleService;
import com.hai.service.CmsCategoryService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service(value = "cmsCategoryService")
public class CmsCategoryServiceImpl implements CmsCategoryService {

    @Resource
    private CmsCategoryMapper cmsCategoryMapper;
    @Resource
    private CmsCategoryRoleService cmsCategoryRoleService;

    @Override
    @Transactional
    public int addCategory(CmsCategory cmsCategory, List<Integer> roleList) throws Exception {
        // 插入分类
        cmsCategory.setCode("CMS_" + cmsCategory.getCode());
        cmsCategory.setStatus(1);
        // 验证是否存在相同编码的分类
        isCategoryExists(cmsCategory);

        cmsCategoryMapper.insertSelective(cmsCategory);

        // 插入分类角色关联
        return cmsCategoryRoleService.addCategoryRoles(cmsCategory.getId(), roleList);
    }

    @Override
    @Transactional
    public int updateCategory(CmsCategory cmsCategory, List<Integer> roleList) throws Exception {
        CmsCategory category = cmsCategoryMapper.selectByPrimaryKey(cmsCategory.getId());
        if (category == null || category.getStatus() == 0) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.CMS_CATEGORY_NOT_FOUND, "");
        }

        // 验证是否存在相同编码的分类
        isCategoryExists(cmsCategory);
        // 变更父级分类时，验证变更后父级菜单的权限不少于子级菜单的权限
        /*if (!category.getParentId().equals(cmsCategory.getParentId())) {
            List<Integer> rolesOfCategory = getRolesOfCategory(cmsCategory.getParentId());
            if (!rolesOfCategory.containsAll(roleList)) {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.CMS_CATEGORY_ROLE_SURPLUS, "");
            }
        }*/

        /**
         * 移除子级菜单中父级菜单没有的权限
         */
        // 查询子级菜单列表
        List<CmsCategory> children = new ArrayList<>();
        children.add(cmsCategory);
        for (int i = 0; i < children.size(); i++) {
            List<CmsCategory> subs = getCategoryChildren(children.get(i).getId());    // 查询当前节点的子节点
            children.addAll(subs);
        }
        // 从子级菜单列表中过滤id
        List<Long> childIds = children.stream().map(CmsCategory::getId).collect(Collectors.toList());
        // 移除子级菜单中不在roleList里的权限
        cmsCategoryRoleService.delSurplusRolesOfCategories(childIds, roleList);

        // 修改分类
        if(cmsCategory.getStatus() == null){
            cmsCategory.setStatus(category.getStatus());
        }
        cmsCategory.setCode(category.getCode());
        cmsCategory.setParentId(category.getParentId());
        cmsCategoryMapper.updateByPrimaryKey(cmsCategory);

        // 增加分类角色关联
        return cmsCategoryRoleService.addCategoryRoles(cmsCategory.getId(), roleList);
    }

    @Override
    public int delCategory(Long id) throws Exception {
        CmsCategory category = cmsCategoryMapper.selectByPrimaryKey(id);
        if (category == null || category.getStatus() == 0) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.CMS_CATEGORY_NOT_FOUND, "");
        }

        // 验证是否存在子级分类
        List<CmsCategory> children = getCategoryChildren(category.getId());
        if (children != null && children.size() > 0) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.CMS_CATEGORY_EXISTS_CHILDREN, "");
        }

        category.setStatus(0);
        return cmsCategoryMapper.updateByPrimaryKey(category);
    }

    @Override
    public CmsCategory getCategoryById(Long id) throws Exception {
        return cmsCategoryMapper.selectByPrimaryKey(id);
    }

    @Override
    public List<CmsCategoryTreeModel> getCategoryTree(Map<String, Object> paramsMap) throws Exception {
        // 查询分类列表
        List<CmsCategory> categoryList = getCategoryList(paramsMap);
        List<CmsCategoryTreeModel> resultList = new ArrayList<>();

        // 获取根节点
        String code = String.valueOf(paramsMap.get("parentCode"));
        for (CmsCategory category : categoryList) {
            CmsCategoryTreeModel node = new CmsCategoryTreeModel();
            node.setId(category.getId());
            node.setCode(category.getCode());
            node.setText(category.getName());
            node.setRemark(category.getRemark());
            node.setCoverImg(category.getCoverImg());
            if (category.getExt1() != null) {
                JSONObject jsonObject = JSONObject.parseObject(category.getExt1());
                node.setUnitInfo(jsonObject);
            }
            node.setExt1(category.getExt1());
            node.setExt2(category.getExt2());
            node.setExt3(category.getExt3());

            if ("null".equals(code)) {
                if (category.getParentId() == null) {
                    resultList.add(node);
                }
            } else if (code.equals(category.getCode())) {
                resultList.add(node);
                break;
            }
        }

        // 构建分类树
        for (CmsCategoryTreeModel treeModel : resultList) {
            buildTree(treeModel, categoryList);
        }

        return resultList;
    }

    @Override
    public List<CmsCategoryTreeModel> getOwnCategoryTree(Map<String, Object> paramsMap) throws Exception {
        // 查询分类列表
        List<CmsCategory> categoryList = getOwnCategoryList(paramsMap);

        List<CmsCategoryTreeModel> resultList = new ArrayList<>();

        // 获取根节点
        for (CmsCategory category : categoryList) {
            if (category.getParentId() == null) {
                CmsCategoryTreeModel node = new CmsCategoryTreeModel();
                node.setId(category.getId());
                node.setCode(category.getCode());
                node.setText(category.getName());
                resultList.add(node);
            }
        }

        // 构建分类树
        for (CmsCategoryTreeModel treeModel : resultList) {
            buildTree(treeModel, categoryList);
        }

        return resultList;
    }

    private void buildTree(CmsCategoryTreeModel root,
                           List<CmsCategory> categoryList) throws Exception {
        // 获取子节点
        List<CmsCategory> children = categoryList.stream()
                .filter(category -> root.getId().equals(category.getParentId()))
                .collect(Collectors.toList());

        if (children == null || children.size() == 0) {
            return ;
        }

        // 插入子节点，并迭代
        for (CmsCategory category : children) {
            CmsCategoryTreeModel node = new CmsCategoryTreeModel();
            node.setId(category.getId());
            node.setCode(category.getCode());
            node.setParentId(category.getParentId());
            node.setText(category.getName());
            node.setRemark(category.getRemark());
            node.setCoverImg(category.getCoverImg());
            if (category.getExt1() != null) {
                JSONObject jsonObject = JSONObject.parseObject(category.getExt1());
                node.setUnitInfo(jsonObject);
            }
            node.setExt1(category.getExt1());
            node.setExt2(category.getExt2());
            node.setExt3(category.getExt3());
            root.addChild(node);

            buildTree(node, categoryList);
        }
    }

    @Override
    public List<CmsCategory> getCategoryList(Map<String, Object> paramsMap) throws Exception {
        return cmsCategoryMapper.getCategoryList(paramsMap);
    }

    @Override
    public List<CmsCategory> getOwnCategoryList(Map<String, Object> paramsMap) throws Exception {
        return cmsCategoryMapper.getOwnCategoryList(paramsMap);
    }

    @Override
    public List<CmsCategory> getCategoryChildren(Long id) throws Exception {
        CmsCategoryExample example = new CmsCategoryExample();
        CmsCategoryExample.Criteria criteria = example.createCriteria();

        criteria.andParentIdEqualTo(id);
        criteria.andStatusNotEqualTo(0);

        return cmsCategoryMapper.selectByExample(example);
    }

    @Override
    public List<Integer> getRolesOfCategory(Long id) throws Exception {
        return cmsCategoryMapper.getRolesOfCategory(id);
    }

    /**
     *
     * @Description: 验证是否存在相同名称或编码的分类
     */
    private Boolean isCategoryExists(CmsCategory cmsCategory) throws Exception {

        List<CmsCategory> categoryList = cmsCategoryMapper.getCategoryListByCode(cmsCategory);
        if (categoryList != null && categoryList.size() > 1) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.CMS_CATEGORY_EXISTS, "");
        } else if (categoryList != null && categoryList.size() == 1 && !categoryList.get(0).getId().equals(cmsCategory.getId())) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.CMS_CATEGORY_EXISTS, "");
        }

        return false;
    }
}
