package com.mortals.xhx.module.area.service.impl;

import com.mortals.framework.exception.AppException;
import com.mortals.framework.model.Context;
import com.mortals.framework.service.impl.AbstractCRUDCacheServiceImpl;
import com.mortals.xhx.common.code.SatusEnum;
import com.mortals.xhx.module.area.dao.AreaDao;
import com.mortals.xhx.module.area.model.AreaEntity;
import com.mortals.xhx.module.area.model.AreaQuery;
import com.mortals.xhx.module.area.model.AreaTreeSelect;
import com.mortals.xhx.module.area.service.AreaService;
import com.mortals.xhx.module.site.service.SiteService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * AreaService
 * 区域 service实现
 *
 * @author zxfei
 * @date 2022-01-12
 */
@Service("areaService")
public class AreaServiceImpl extends AbstractCRUDCacheServiceImpl<AreaDao, AreaEntity, Long> implements AreaService {

    @Autowired
    private SiteService siteService;


/*    @Override
    public void putCache(String key, AreaEntity data) {
        super.putCache(key, data);
        //加载孩子关系
        if ("True".equalsIgnoreCase(data.getHaveSonArea())) {
            String childKey = super.getCacheName() + ":" + data.getIid();
            //cacheService.del(childKey);
            this.find(new AreaQuery().pid(data.getIid())).stream().forEach(item -> {
                cacheService.lpush(childKey, item);
            });
        }
    }*/

    @Override
    protected String getExtKey(AreaEntity data) {
        return data.getAreaCode();
    }

    @Override
    protected void saveBefore(AreaEntity entity, Context context) throws AppException {
        AreaEntity parentAreaEntity = this.selectOne(new AreaQuery().pid(entity.getPid()));
        if (!ObjectUtils.isEmpty(parentAreaEntity) && SatusEnum.DISENABLE.getValue() == parentAreaEntity.getStatus()) {
            throw new AppException("区域停用，不允许新增");
        }

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

        super.saveBefore(entity, context);
    }

    @Override
    protected void updateBefore(AreaEntity entity, Context context) throws AppException {
        AreaEntity newParentEntity = this.selectOne(new AreaQuery().pid(entity.getPid()));
        AreaEntity 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);
            updateAreaChildren(entity.getId(), newAncestors, oldAncestors, context);
        }
        super.updateBefore(entity, context);
    }


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

    /**
     * 修改该区域的父级区域状态
     *
     * @param area 当前区域
     */
    private void updateParentAreaStatus(AreaEntity area, Context context) {
        AreaEntity areaEntity = this.selectOne(new AreaQuery().pid(area.getPid()));

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

    /**
     * 修改子元素关系
     *
     * @param areaId       被修改的区域ID
     * @param newAncestors 新的父ID集合
     * @param oldAncestors 旧的父ID集合
     */
    public void updateAreaChildren(Long areaId, String newAncestors, String oldAncestors, Context context) {

        List<AreaEntity> children = getDao().selectChildrenAreaById(areaId.toString());

        for (AreaEntity 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 {
        //有子节点 禁止删除 todo
//        if (hasChildByAreaId(ids[0])) {
//            throw new AppException("存在下级区域,不允许删除");
//        }
        super.removeBefore(ids, context);
    }

    @Override
    public boolean hasChildByAreaId(String areaId) {
        List<AreaEntity> list = this.find(new AreaQuery().pid(areaId));
        return list.size() > 0 ? true : false;
    }

    @Override
    public List<AreaEntity> selectAreaList(AreaEntity area) {
        return this.find(new AreaQuery());
    }

    @Override
    public List<AreaTreeSelect> buildAreaTreeSelect(List<AreaEntity> list) {
        List<AreaEntity> returnList = new ArrayList<>();
        List<Long> tempList = list.stream().map(AreaEntity::getId).collect(Collectors.toList());
        for (AreaEntity areaEntity : list) {
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(areaEntity.getPid())) {
                recursionFn(list, areaEntity);
                returnList.add(areaEntity);
            }
        }
        if (returnList.isEmpty()) {
            returnList = list;
        }

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

    @Override
    public List<AreaTreeSelect> getListByParentId(String parentId, Context context) {
        if (ObjectUtils.isEmpty(parentId)) {
            parentId = "0";
        }
        //只做一层
        List<AreaTreeSelect> collect = this.find(new AreaQuery().pid(parentId), context).stream().map(item -> new AreaTreeSelect(item)
        ).collect(Collectors.toList());
        if ("0".equals(parentId)) {
            return collect;
        }
//        AreaEntity areaEntity = this.selectOne(new AreaQuery().iid(parentId));
//        if (!ObjectUtils.isEmpty(areaEntity)) {
//            //查询当前区域是否有站点。
//            List<AreaTreeSelect> collect1 = siteService.find(new SiteQuery().areaCode(areaEntity.getAreaCode()))
//                    .stream().map(site -> new AreaTreeSelect(site)).collect(Collectors.toList());
//            collect.addAll(collect1);
//
//        }
        return collect;
    }

    @Override
    public List<AreaTreeSelect> getListByRootId(String rootId, Context context) {
        if (ObjectUtils.isEmpty(rootId)) {
            rootId = "0";
        }

        AreaEntity areaEntity = this.selectOne(new AreaQuery().pid(rootId));

        AreaTreeSelect areaTreeSelect = new AreaTreeSelect(areaEntity);

        rebuildList(areaTreeSelect);

        List<AreaTreeSelect> areaTreeSelectList = new ArrayList<>();
        areaTreeSelectList.add(areaTreeSelect);

        return areaTreeSelectList;
    }

    private void rebuildList(AreaTreeSelect areaTreeSelect) {
        List<AreaTreeSelect> list = this.cacheService.lrange(super.getCacheName() + ":" + areaTreeSelect.getId(), AreaEntity.class).stream().map(item -> new AreaTreeSelect(item)).collect(Collectors.toList());
        list.stream().forEach(item -> {
            rebuildList(item);
        });
        areaTreeSelect.setChildren(list);

    }


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

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

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


}