package com.yeejoin.amos.fas.business.service.impl;

import com.yeejoin.amos.fas.business.dao.repository.IPlanClassifyTreeDao;
import com.yeejoin.amos.fas.business.dao.repository.IPlanDetailDao;
import com.yeejoin.amos.fas.business.service.intfc.IPlanClassifyTreeService;
import com.yeejoin.amos.fas.business.util.TreeUtil;
import com.yeejoin.amos.fas.business.vo.PlanClassifyTreeVo;
import com.yeejoin.amos.fas.dao.entity.PlanClassifyTree;
import com.yeejoin.amos.fas.exception.YeeException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
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 java.util.*;

/**
 * @program: YeeAmosFireAutoSysRoot
 * @description: 预案分类树实现类
 * @author: wujunkai
 * @create: 2021-01-14 14:59
 */
@Service("PlanClassifyTreeService")
public class PlanClassifyTreeServiceImpl implements IPlanClassifyTreeService {
    public static final Long ROOT = 0L;

    @Autowired
    private IPlanClassifyTreeDao planClassifyTreeDao;
    @Autowired
    private IPlanDetailDao planDetailDao;

    @Override
    public PlanClassifyTree save(PlanClassifyTree model) {
        return planClassifyTreeDao.save(model);
    }

    @Override
    @Transactional(rollbackFor = {YeeException.class, Exception.class})
    public Boolean delete(String ids) {
        List<Long> seqs = StringUtil.String2LongList(ids);
        Set allIds = new HashSet<>(seqs);
        for (Long seq : seqs) {
            List<PlanClassifyTreeVo> allChildIncludeMe = getAllChildIncludeMe(seq);
            allIds.addAll(Bean.listToMap(TreeUtil.getAllChildren(allChildIncludeMe), "id", "id", PlanClassifyTreeVo.class).keySet());
        }
        // 查询分类下是否有预案
        if (planDetailDao.existsByClassifyIdInAndIsDelete(allIds, false)) {
            throw new YeeException("目录下存在预案");
        }
        planClassifyTreeDao.deleteByIdIn(allIds);
        return true;
    }

    @Override
    public Collection<PlanClassifyTreeVo> getTree() {
        List<PlanClassifyTree> list = planClassifyTreeDao.findAll();
        List<PlanClassifyTreeVo> voList = new ArrayList<>();
        for (PlanClassifyTree planClassifyTree : list) {
            PlanClassifyTreeVo planClassifyTreeVo = new PlanClassifyTreeVo();
            BeanUtils.copyProperties(planClassifyTree, planClassifyTreeVo);
            voList.add(planClassifyTreeVo);
        }
        Map<Object, PlanClassifyTreeVo> map = Bean.listToMap(voList, "id", PlanClassifyTree.class);

        SortedSet<PlanClassifyTreeVo> completeList = new TreeSet<>();
        for (PlanClassifyTreeVo model : voList) {
            completeList.addAll(buildWithParent(model, map));
        }
        return TreeBuilder.buildByRecursive(completeList, ROOT);
    }

    private List<PlanClassifyTreeVo> buildWithParent(PlanClassifyTreeVo groupModel, Map<Object, PlanClassifyTreeVo> map) {

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

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

        PlanClassifyTreeVo parent = map.get(groupModel.getParentId());
        if (ValidationUtil.isEmpty(parent)) {
            parent = (PlanClassifyTreeVo) this.planClassifyTreeDao.findById(groupModel.getParentId()).get();

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

    @Override
    public List<PlanClassifyTreeVo> getAllChildIncludeMe(Long root) {
        List<PlanClassifyTreeVo> treeDaoAll = Bean.toModels(planClassifyTreeDao.getAll(), PlanClassifyTreeVo.class);
        Collection<PlanClassifyTreeVo> treeList = TreeBuilder.bulid(treeDaoAll, root);
        if (!ROOT.equals(root)) {
            PlanClassifyTree classifyTree = planClassifyTreeDao.findById(root).orElse(null);
            if (null != classifyTree) {
                PlanClassifyTreeVo classifyTreeVo = Bean.toModel(classifyTree, new PlanClassifyTreeVo());
                classifyTreeVo.setChildren(treeList);
                return Arrays.asList(classifyTreeVo);
            }
        }
        return new ArrayList<>(treeList);
    }

    @Override
    public PlanClassifyTree create(PlanClassifyTree model) {
        if (ValidationUtil.isEmpty(model.getClassifyName()) || ValidationUtil.isEmpty(model.getParentId())) {
            throw new YeeException("参数有误");
        }
        if (classifyNameExist(model.getClassifyName(), model.getParentId())) {
            throw new YeeException("名称重复");
        }
        model.setId(0);
        return planClassifyTreeDao.save(model);
    }

    @Override
    public PlanClassifyTree update(PlanClassifyTree model) {
        if (ValidationUtil.isEmpty(model.getId()) || ValidationUtil.isEmpty(model.getClassifyName()) || ValidationUtil.isEmpty(model.getParentId())) {
            throw new YeeException("参数有误");
        }
        if (!planClassifyTreeDao.existsById(model.getId())) {
            throw new YeeException("原数据不存在");
        }
        if (classifyNameExist(model.getClassifyName(), model.getParentId())) {
            throw new YeeException("名称重复");
        }
        return planClassifyTreeDao.save(model);
    }

    private boolean classifyNameExist(String classifyName, Long parentId) {
        return 0 < planClassifyTreeDao.countByClassifyNameAndParentId(classifyName, parentId);
    }
}