package com.mortals.xhx.module.demotree.service.impl;
import org.springframework.stereotype.Service;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.model.Context;
import com.mortals.xhx.common.code.SatusEnum;
import com.mortals.framework.service.impl.AbstractCRUDServiceImpl;
import com.mortals.xhx.module.demotree.dao.DemotreeDao;
import com.mortals.xhx.module.demotree.model.DemotreeEntity;
import com.mortals.xhx.module.demotree.model.DemotreeQuery;
import com.mortals.xhx.module.demotree.service.DemotreeService;
import com.mortals.xhx.module.demotree.model.DemotreeTreeSelect;
import org.springframework.util.ObjectUtils;
import java.util.*;
import java.util.stream.Collectors;



/**
* DemotreeService
* 树信息 service实现
*
* @author zxfei
* @date 2021-11-26
*/
@Service("demotreeService")
public class DemotreeServiceImpl extends AbstractCRUDServiceImpl<DemotreeDao, DemotreeEntity, Long> implements DemotreeService {

    @Override
    protected void saveBefore(DemotreeEntity entity, Context context) throws AppException {
        DemotreeEntity parentDemotreeEntity = this.get(entity.getParentId());
        if (!ObjectUtils.isEmpty(parentDemotreeEntity) && SatusEnum.DISENABLE.getValue() == parentDemotreeEntity.getStatus()) {
            throw new AppException("树信息停用，不允许新增");
        }

        if (!ObjectUtils.isEmpty(parentDemotreeEntity)) {
            entity.setAncestors(parentDemotreeEntity.getAncestors() + "," + entity.getParentId());
        }

        super.saveBefore(entity, context);
    }

    @Override
    protected void updateBefore(DemotreeEntity entity, Context context) throws AppException {
        DemotreeEntity newParentEntity = this.get(entity.getParentId());
        DemotreeEntity oldEntity = this.get(entity.getId());
        if (!ObjectUtils.isEmpty(newParentEntity) && !ObjectUtils.isEmpty(oldEntity)) {
            String newAncestors = newParentEntity.getAncestors() + "," + newParentEntity.getId();
            String oldAncestors = oldEntity.getAncestors();
            entity.setAncestors(newAncestors);
            updateDemotreeChildren(entity.getId(), newAncestors, oldAncestors, context);
        }
        super.updateBefore(entity, context);
    }


    @Override
    protected void updateAfter(DemotreeEntity entity, Context context) throws AppException {
        if (SatusEnum.ENABLE.getValue() == entity.getStatus()) {
            updateParentDemotreeStatus(entity, context);
        }
        super.updateAfter(entity, context);
    }

    /**
    * 修改该树信息的父级树信息状态
    *
    * @param demotree 当前树信息
    */
    private void updateParentDemotreeStatus(DemotreeEntity demotree, Context context) {
        DemotreeEntity demotreeEntity = this.get(demotree.getParentId());

        demotreeEntity.setStatus(SatusEnum.ENABLE.getValue());
        demotreeEntity.setUpdateTime(new Date());
        demotreeEntity.setUpdateUser(context.getUser().getLoginName());
        DemotreeEntity condition = new DemotreeEntity();
        condition.setId(demotreeEntity.getId());
        this.updateBatch(demotreeEntity, condition, context);
    }

    /**
    * 修改子元素关系
    *
    * @param demotreeId       被修改的树信息ID
    * @param newAncestors 新的父ID集合
    * @param oldAncestors 旧的父ID集合
    */
    public void updateDemotreeChildren(Long demotreeId, String newAncestors, String oldAncestors, Context context) {

        List<DemotreeEntity> children =  getDao().selectChildrenDemotreeById(demotreeId.toString());

        for (DemotreeEntity child : children) {
            child.setAncestors(child.getAncestors().replace(oldAncestors, newAncestors));
        }
        if (children.size() > 0) {
            this.updateAfter(children, context);
        }
    }


    @Override
    protected void removeBefore(Long[] ids, Context context) throws AppException {
        //有子节点 禁止删除
        if (hasChildByDemotreeId(ids[0])) {
            throw new AppException("存在下级树信息,不允许删除");
        }
        super.removeBefore(ids, context);
    }

    @Override
    public boolean hasChildByDemotreeId(Long demotreeId) {
        List<DemotreeEntity> list = this.find(new DemotreeQuery().parentId(demotreeId));
        return list.size() > 0 ? true : false;
    }

    @Override
    public List<DemotreeEntity> selectDemotreeList(DemotreeEntity demotree) {
        return this.find(new DemotreeQuery());
    }

    @Override
    public List<DemotreeTreeSelect> buildDemotreeTreeSelect(List<DemotreeEntity> list) {
        List<DemotreeEntity> returnList = new ArrayList<>();
        List<Long> tempList = list.stream().map(DemotreeEntity::getId).collect(Collectors.toList());

        for (Iterator<DemotreeEntity> iterator = list.iterator(); iterator.hasNext(); ) {
            DemotreeEntity demotreeEntity = iterator.next();
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(demotreeEntity.getParentId())) {
                recursionFn(list, demotreeEntity);
                returnList.add(demotreeEntity);
            }
            }
            if (returnList.isEmpty()) {
            returnList = list;
        }

        return returnList.stream().map(DemotreeTreeSelect::new).collect(Collectors.toList());
    }


    /**
    * 递归列表
    */
    private void recursionFn(List<DemotreeEntity> list, DemotreeEntity t) {
        // 得到子节点列表
        List<DemotreeEntity> childList = getChildList(list, t);
        t.setChildren(childList);
        for (DemotreeEntity tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    /**
    * 判断是否有子节点
    */
    private boolean hasChild(List<DemotreeEntity> list, DemotreeEntity t) {
        return getChildList(list, t).size() > 0 ? true : false;
    }

    /**
    * 得到子节点列表
    */
    private List<DemotreeEntity> getChildList(List<DemotreeEntity> list, DemotreeEntity t) {
        return list.stream().map(item->{
            if (!ObjectUtils.isEmpty(item.getParentId()) && item.getParentId() == t.getId()) {
                return item;
            }
            return null;
            }).filter(f->f!=null).collect(Collectors.toList());
    }

}