package com.xxfc.platform.universal.biz;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.ace.cache.annotation.Cache;
import com.ace.cache.annotation.CacheClear;
import com.github.wxiaoqi.security.common.biz.BaseBiz;
import com.github.wxiaoqi.security.common.msg.ObjectRestResponse;
import com.google.common.collect.Lists;
import com.xxfc.platform.universal.entity.Dictionary;
import com.xxfc.platform.universal.mapper.DictionaryMapper;
import com.xxfc.platform.universal.vo.DictionaryVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.xxfc.platform.universal.constant.RedisKey.*;

@Service
@Slf4j
public class DictionaryBiz extends BaseBiz<DictionaryMapper, Dictionary> {

    public ObjectRestResponse add(Dictionary dictionary) {
        if(dictionary == null)
            return ObjectRestResponse.paramIsEmpty();
        List<Dictionary> dictionaryVos = mapper.selectByCodeAndType(dictionary);
        if(dictionaryVos.size() == 1) {//已有数据 直接更新
            BeanUtil.copyProperties(dictionary, dictionaryVos.get(0), CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
            mapper.updateByPrimaryKeySelective(dictionaryVos.get(0));
            return ObjectRestResponse.succ();
        }
        if(dictionary.getPid() != null) {//有父类 判断是否存在
            Dictionary parent = mapper.selectByPrimaryKey(dictionary.getPid());
            if(parent == null) {
                log.info("pid所属数据不存在, dictionary = {}", dictionary);
                return ObjectRestResponse.createFailedResult(500, "pid所属数据不存在");
            }
        } else { //没有父类设置pid为0
            dictionary.setPid(0);
        }
        mapper.insertSelective(dictionary);
        return ObjectRestResponse.succ();
    }

    public ObjectRestResponse<List<Dictionary>> get(Dictionary dictionary) {
        if(dictionary == null) {
            return ObjectRestResponse.paramIsEmpty();
        }
        List<Dictionary> dictionaryList = mapper.selectByCodeAndType(dictionary);
        for(Dictionary parent : dictionaryList) {
            Set<Dictionary> dictionaryVoList = buildTree(parent.getId());
            parent.setChildrens(dictionaryVoList);
        }

        return ObjectRestResponse.succ(dictionaryList);
    }

    public ObjectRestResponse deleteByEntity(Dictionary dictionary) {
        if(dictionary == null) {
            return ObjectRestResponse.paramIsEmpty();
        }
        //删除所有子元素
        Set<Dictionary> childrens = mapper.selectByPid(dictionary.getId());
       if(childrens.size() > 0) {
           childrens.forEach((a) -> mapper.deleteByPrimaryKey(a));
       }
        mapper.deleteByPrimaryKey(dictionary);
        return ObjectRestResponse.succ();
    }

    public ObjectRestResponse update(Dictionary dictionary) {
        if(StringUtils.isEmpty(dictionary)) {
            return ObjectRestResponse.paramIsEmpty();
        }
        Dictionary oldValue = mapper.selectByPrimaryKey(dictionary.getId());
        BeanUtil.copyProperties(dictionary, oldValue, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        mapper.updateByPrimaryKeySelective(oldValue);
        return ObjectRestResponse.succ();
    }

    public ObjectRestResponse<List<Dictionary>> getParent(String type) {
        if(StringUtils.isEmpty(type)) {
            return ObjectRestResponse.paramIsEmpty();
        }
        List<Dictionary> dictionaryList = getParentCommon(type);
        return ObjectRestResponse.succ(dictionaryList);
    }

    private List<Dictionary> getParentCommon(String type) {
        Dictionary dictionary = new Dictionary();
        dictionary.setType(type);
        dictionary.setPid(0);
        List<Dictionary> dictionaryList = mapper.selectByCodeAndType(dictionary);
        for(Dictionary parent : dictionaryList) {
            Set<Dictionary> dictionaryVoList = buildTree(parent.getId());
            parent.setChildrens(dictionaryVoList);
        }
        return dictionaryList;
    }

    @Cache(key = CACHE_DICTIONARY_ALL_MAP)
    public Map<String, Dictionary> getAll4Map(){
//        List<Dictionary> dictionaries = this.getParentCommon(null);
        List<Dictionary> dictionaries = selectListAll();
        Map<String, Dictionary> dictionaryMap = dictionaries.parallelStream().collect(Collectors.toMap(dic -> dic.getType()+ "_"+ dic.getCode()
                , Function.identity(), (oldValue, newValue) -> newValue));
        dictionaryMap.forEach((k,v) -> {
            v.setChildrens(buildTree(v.getId()));
        });
        return dictionaryMap;
    }

    @CacheClear(pre = CACHE_DICTIONARY_PREFIX)
    public void clear(){
        ;
    }

    public DictionaryVo buidTree(Dictionary dictionary) {
        DictionaryVo dictionaryVo = new DictionaryVo();
        if(dictionary.getPid() == 0) {
            BeanUtil.copyProperties(dictionary, dictionaryVo, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
            Set<Dictionary> childrens = mapper.selectByPid(dictionary.getId());
            dictionaryVo.setChildrens(childrens);
            for(Dictionary children : childrens) {
                buidTree(children);
            }
        }
        return dictionaryVo;
    }

    public  Set<Dictionary> buildTree(int parentId) {
        Set<Dictionary> childrens = mapper.selectByPid(parentId);
        Set<Dictionary> dictionaryVoList = new HashSet<>();
        for (Dictionary dictionary : childrens) {
            int dictionaryId = dictionary.getId();
            int pid = dictionary.getPid();
            if (parentId == pid) {

                Set<Dictionary> menuLists = buildTree(dictionaryId);
                dictionary.setChildrens(menuLists);
                dictionaryVoList.add(dictionary);
            }
        }
        return dictionaryVoList;
    }

    public Dictionary findDictionaryByTypeAndCode(String type, String code) {
        Dictionary dictionary = new Dictionary();
         dictionary.setType(type);
         dictionary.setCode(code);
        return  mapper.selectOne(dictionary);
    }
}
