package com.lightinit.hsdataplatform.impl.admin;

import com.lightinit.hsdataplatform.common.SysContants;
import com.lightinit.hsdataplatform.dictionary.DicModuleActionType;
import com.lightinit.hsdataplatform.dictionary.DicResourceType;
import com.lightinit.hsdataplatform.entity.Menu;
import com.lightinit.hsdataplatform.entity.MenuExample;
import com.lightinit.hsdataplatform.entity.ModuleAction;
import com.lightinit.hsdataplatform.entity.ModuleActionExample;
import com.lightinit.hsdataplatform.mapper.MenuMapper;
import com.lightinit.hsdataplatform.mapper.ModuleActionMapper;
import com.lightinit.hsdataplatform.model.ResultState;
import com.lightinit.hsdataplatform.model.ResultStateCode;
import com.lightinit.hsdataplatform.model.admin.ModuleActionListItemModel;
import com.lightinit.hsdataplatform.model.admin.ModuleDataModel;
import com.lightinit.hsdataplatform.model.admin.ModuleWithActionListModel;
import com.lightinit.hsdataplatform.model.admin.TreeModel;
import com.lightinit.hsdataplatform.service.admin.IModuleMgrService;
import com.lightinit.hsdataplatform.service.admin.TreeDataBuilder;
import com.lightinit.hsdataplatform.spring.DynamicDataContextHolder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.function.Function;

import static java.util.stream.Collectors.toList;

/**
 * @author WangYao
 * @date 2018/6/30 13:10
 * @description 模块管理业务实现
 */
@Service
public class ModuleMgrServiceImpl implements IModuleMgrService {
    @Autowired
    private MenuMapper menuMapper;
    @Autowired
    private ModuleActionMapper moduleActionMapper;

    @Cacheable(value = SysContants.CacheName.MODULE_ACTION_CACHE)
    public List<ModuleActionListItemModel> getModuleActionList() {
        DynamicDataContextHolder.setCustomerType(DynamicDataContextHolder.DEFAULT);
        return menuMapper.selectModuleActionList();
    }

    public List<TreeModel> queryTreeData() {
        DynamicDataContextHolder.setCustomerType(DynamicDataContextHolder.DEFAULT);
        final List<Menu> moduleList = getAllMenuList();

        ModuleActionExample example2 = new ModuleActionExample();
        ModuleActionExample.Criteria criteria2 = example2.createCriteria();
        List<ModuleAction> allActionList = moduleActionMapper.selectByExample(example2);

        List<ModuleWithActionListModel> dataList = new ArrayList<>();
        for (Menu module : moduleList) {
            ModuleWithActionListModel moduleWithAction = new ModuleWithActionListModel();
            BeanUtils.copyProperties(module, moduleWithAction);
            dataList.add(moduleWithAction);
            if (allActionList != null && allActionList.size() > 0) {
                moduleWithAction.setModuleActionList(allActionList.stream().filter(q -> q.getModuleId().equals(moduleWithAction.getId())).collect(toList()));
            }
        }

        Function<ModuleAction,TreeModel> actionMapFunction = (q) -> {
            TreeModel treeModel =  new TreeModel(q.getId().toString(), null, q.getActionName(), null);
            treeModel.setState(treeModel.new State(false, false, false, false));
            List<String> tags = new ArrayList<>();
            tags.add(String.valueOf(DicModuleActionType.ACTION));
            treeModel.setTags(tags);
            return treeModel;
        };

        Function<ModuleWithActionListModel,TreeModel> moduleMapFunction = (q) -> {
            // 模块
            TreeModel treeModel =  new TreeModel(q.getId().toString(), null, q.getMenuname(), null);
            treeModel.setState(treeModel.new State(false, false, false, false));
            List<String> tags = new ArrayList<>();
            tags.add(String.valueOf(DicModuleActionType.MODULE));
            treeModel.setTags(tags);
            // Action
            if (q.getModuleActionList() != null && q.getModuleActionList().size() > 0){
                List<TreeModel> childNodes = q.getModuleActionList().stream().map(actionMapFunction).collect(toList());
                if (childNodes != null && childNodes.size() > 0){
                    treeModel.getState().setExpanded(false);
                }
                treeModel.setNodes(childNodes);
            }
            return treeModel;
        };

        List<TreeModel> treeModelList = dataList.stream().filter(q -> q.getParentmenu() == null).map(moduleMapFunction).collect(toList());
        TreeDataBuilder.buildTreeModelRecursively(treeModelList, dataList, (pCurrentTreeModel, pDataList) -> {
            return pDataList.stream()
                    .filter(q -> q.getParentmenu() != null && q.getParentmenu().toString().equals(pCurrentTreeModel.getId()))
                    .map(moduleMapFunction)
                    .collect(toList());
        });
        return treeModelList;
    }

    public List<Menu> getAllMenuList(){
        DynamicDataContextHolder.setCustomerType(DynamicDataContextHolder.DEFAULT);
        MenuExample example1 = new MenuExample();
        MenuExample.Criteria criteria1 = example1.createCriteria();
        criteria1.andMenushowEqualTo(1);
        return menuMapper.selectByExample(example1);
    }

    public List<ModuleAction> getAllActionList(){
        DynamicDataContextHolder.setCustomerType(DynamicDataContextHolder.DEFAULT);
        ModuleActionExample example1 = new ModuleActionExample();
//        ModuleActionExample.Criteria criteria1 = example1.createCriteria();
        return moduleActionMapper.selectByExample(example1);
    }

    @CacheEvict(value = SysContants.CacheName.MODULE_ACTION_CACHE, allEntries = true)
    @Transactional
    public ResultState addOrEdit(ModuleDataModel inputModel){
        DynamicDataContextHolder.setCustomerType(DynamicDataContextHolder.DEFAULT);
        ResultState resultState;

        if (DicModuleActionType.MODULE.equals(inputModel.getObjType())){
            resultState = addOrEditModule(inputModel);
        }else {
            resultState = addOrEditAction(inputModel);
        }

        return resultState;
    }

    @CacheEvict(value = SysContants.CacheName.MODULE_ACTION_CACHE, allEntries = true)
    @Transactional
    public ResultState<Menu> addOrEditModule(ModuleDataModel inputModel){
        DynamicDataContextHolder.setCustomerType(DynamicDataContextHolder.DEFAULT);
        ResultState<Menu> resultState = new ResultState<>();

        int sqlResult1;
        Menu entity1 = new Menu();
        BeanUtils.copyProperties(inputModel, entity1);
        entity1.setMenucode(inputModel.getObjCode());
        entity1.setMenuname(inputModel.getObjName());
        entity1.setMenuaction(inputModel.getObjUrl());
        entity1.setParentmenu(inputModel.getModuleId());
        entity1.setMenutype(0);
        entity1.setMenusequence(1);
        entity1.setMenushow(1);
        if (inputModel.getId() == null){
            Date createdAt = new Date();
            entity1.setAddtime(createdAt);
            sqlResult1 = menuMapper.insert(entity1);
        }else {
            MenuExample example1 = new MenuExample();
            MenuExample.Criteria criteria1 = example1.createCriteria();
            criteria1.andIdEqualTo(inputModel.getId());
            sqlResult1 = menuMapper.updateByExampleSelective(entity1, example1);
        }

        if (!(sqlResult1 > 0)){
            resultState.setStateCode(ResultStateCode.INVALID_DATA);
            resultState.setMsg(inputModel.getId() == null ? "数据插入失败" : "数据更新失败");
        }
        resultState.setData(menuMapper.selectByPrimaryKey(entity1.getId()));
        return resultState;
    }

    @CacheEvict(value = SysContants.CacheName.MODULE_ACTION_CACHE, allEntries = true)
    @Transactional
    public ResultState<ModuleAction> addOrEditAction(ModuleDataModel inputModel){
        DynamicDataContextHolder.setCustomerType(DynamicDataContextHolder.DEFAULT);
        ResultState<ModuleAction> resultState = new ResultState<>();

        int sqlResult1;
        ModuleAction entity1 = new ModuleAction();
        BeanUtils.copyProperties(inputModel, entity1);
        entity1.setActionCode(inputModel.getObjCode());
        entity1.setActionName(inputModel.getObjName());
        entity1.setActionUrl(inputModel.getObjUrl());
        if (inputModel.getId() == null){
            Date createdAt = new Date();
            entity1.setCreatedAt(createdAt);
            sqlResult1 = moduleActionMapper.insert(entity1);
        }else {
            ModuleActionExample example1 = new ModuleActionExample();
            ModuleActionExample.Criteria criteria1 = example1.createCriteria();
            criteria1.andIdEqualTo(inputModel.getId());
            sqlResult1 = moduleActionMapper.updateByExampleSelective(entity1, example1);
        }

        if (!(sqlResult1 > 0)){
            resultState.setStateCode(ResultStateCode.INVALID_DATA);
            resultState.setMsg(inputModel.getId() == null ? "数据插入失败" : "数据更新失败");
        }
        resultState.setData(moduleActionMapper.selectByPrimaryKey(entity1.getId()));
        return resultState;
    }

    @CacheEvict(value = SysContants.CacheName.MODULE_ACTION_CACHE, allEntries = true)
    @Transactional
    public ResultState<Long> deleteModule(long id) {
        DynamicDataContextHolder.setCustomerType(DynamicDataContextHolder.DEFAULT);
        ResultState<Long> resultState = new ResultState<Long>();

        MenuExample childExample1 = new MenuExample();
        MenuExample.Criteria childCriteria1 = childExample1.createCriteria();
        childCriteria1.andParentmenuEqualTo(id);
        long count1 = menuMapper.countByExample(childExample1);

        ModuleActionExample childExample2 = new ModuleActionExample();
        ModuleActionExample.Criteria childCriteria2 = childExample2.createCriteria();
        childCriteria2.andModuleIdEqualTo(id);
        long count2 = moduleActionMapper.countByExample(childExample2);

        if (count1 > 0 || count2 > 0){
            resultState.setStateCode(ResultStateCode.INVALID_DATA);
            resultState.setMsg("该节点存在子节点，请先删除子节点");
            return resultState;
        }


        MenuExample example1 = new MenuExample();
        MenuExample.Criteria criteria1 = example1.createCriteria();
        criteria1.andIdEqualTo(id);
        int sqlResult1 = menuMapper.deleteByExample(example1);

        if (!(sqlResult1 > 0)){
            resultState.setStateCode(ResultStateCode.INVALID_DATA);
            resultState.setMsg("数据不存在");
        }
        resultState.setData(id);
        return resultState;
    }

    @CacheEvict(value = SysContants.CacheName.MODULE_ACTION_CACHE, allEntries = true)
    @Transactional
    public ResultState<Long> deleteAction(long id) {
        DynamicDataContextHolder.setCustomerType(DynamicDataContextHolder.DEFAULT);
        ResultState<Long> resultState = new ResultState<Long>();

        ModuleActionExample example1 = new ModuleActionExample();
        ModuleActionExample.Criteria criteria1 = example1.createCriteria();
        criteria1.andIdEqualTo(id);
        int sqlResult1 = moduleActionMapper.deleteByExample(example1);

        if (!(sqlResult1 > 0)){
            resultState.setStateCode(ResultStateCode.INVALID_DATA);
            resultState.setMsg("数据不存在");
        }
        resultState.setData(id);
        return resultState;
    }
}
