package com.yeejoin.equipmanage.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.yeejoin.amos.component.feign.model.FeignClientResult;
import com.yeejoin.amos.feign.systemctl.Systemctl;
import com.yeejoin.amos.feign.systemctl.model.DictionarieValueModel;
import com.yeejoin.equipmanage.common.dto.AreaDto;
import com.yeejoin.equipmanage.common.entity.Area;
import com.yeejoin.equipmanage.common.entity.EquipmentSpecific;
import com.yeejoin.equipmanage.common.entity.SourceFile;
import com.yeejoin.equipmanage.common.utils.TreeNodeUtil;
import com.yeejoin.equipmanage.common.vo.AreaResquest;
import com.yeejoin.equipmanage.common.vo.AreaTreeVo;
import com.yeejoin.equipmanage.context.SpringContextHolder;
import com.yeejoin.equipmanage.event.SynAreaRiskEvent;
import com.yeejoin.equipmanage.mapper.AreaMapper;
import com.yeejoin.equipmanage.operation.AreaSynRiskOperator;
import com.yeejoin.equipmanage.service.IAreaService;
import com.yeejoin.equipmanage.service.IEquipmentSpecificSerivce;
import com.yeejoin.equipmanage.service.ISourceFileService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.typroject.tyboot.core.foundation.utils.Bean;

import java.util.*;

/**
 * 区域 服务实现类
 *
 * @author duanwei
 * @date 2021-04-27
 */
@Service
public class AreaServiceImpl extends ServiceImpl<AreaMapper, Area> implements IAreaService {

    @Autowired
    @Lazy
    private ISourceFileService iSourceFileService;

    @Autowired
    @Lazy
    private IEquipmentSpecificSerivce iEquipmentSpecificSerivce;

    @Autowired
    private AreaMapper areaMapper;

    @Value("${systemctl.dict.area-type}")
    private String areaType;

    @Override
    public List<AreaTreeVo> getAreaTreeVo() {
        List<AreaTreeVo> areaTreeList = new ArrayList<>();
        // 查询平台区域数据字典
        FeignClientResult<List<DictionarieValueModel>> dictValues = Systemctl.dictionarieClient.dictValues(areaType);
        if (dictValues != null) {
            List<DictionarieValueModel> values = dictValues.getResult();
            // 根据区域类型查询子节点
            if (values != null && values.size() > 0) {
                for (DictionarieValueModel dictionarieValueModel : values) {
                    AreaTreeVo areaTreeVo = new AreaTreeVo();
                    long parentId = Long.parseLong(dictionarieValueModel.getDictDataKey());
                    areaTreeVo.setId(parentId);
                    areaTreeVo.setName(dictionarieValueModel.getDictDataValue());
                    areaTreeVo.setChildren(getChildren(parentId));
                    areaTreeList.add(areaTreeVo);
                }
            }
        }
        return areaTreeList;
    }

    @Override
    public List<AreaTreeVo> getAreaTreeVoById(long id) {
        List<AreaTreeVo> listTree = new ArrayList<>();
        if (id == -1) {
            listTree = getAreaTreeVo();
        } else {
            listTree = getChildrenz(id);
        }
        return listTree;
    }

    /**
     * 根据父节点查询子节点赋值
     *
     * @param parentId
     * @return
     */
    public List<AreaTreeVo> getChildrenz(Long parentId) {
        List<AreaTreeVo> areaTreeVos = new ArrayList<>();
        LambdaQueryWrapper<Area> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Area::getIsDelete, false);
        queryWrapper.eq(Area::getId, parentId);
        List<Area> areas = this.baseMapper.selectList(queryWrapper);
        if (areas != null && areas.size() > 0) {
            for (Area area : areas) {
                AreaTreeVo areaTreeVo = new AreaTreeVo();
                areaTreeVo.setId(area.getId());
                areaTreeVo.setName(area.getName());
                areaTreeVo.setCode(area.getOrgCode());
                areaTreeVo.setParentId(parentId);
                // 查询子节点赋值
                areaTreeVo.setChildren(getChildren(area.getId()));
                areaTreeVos.add(areaTreeVo);
            }
        }
        return areaTreeVos;
    }

    /**
     * 根据父节点查询子节点赋值
     *
     * @param parentId
     * @return
     */
    public List<AreaTreeVo> getChildren(Long parentId) {
        List<AreaTreeVo> areaTreeVos = new ArrayList<>();
        LambdaQueryWrapper<Area> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Area::getParentId, parentId);
        queryWrapper.eq(Area::getIsDelete, false);
        List<Area> areas = this.baseMapper.selectList(queryWrapper);
        if (areas != null && areas.size() > 0) {
            for (Area area : areas) {
                AreaTreeVo areaTreeVo = new AreaTreeVo();
                areaTreeVo.setId(area.getId());
                areaTreeVo.setName(area.getName());
                areaTreeVo.setCode(area.getOrgCode());
                areaTreeVo.setParentId(parentId);
                // 查询子节点赋值
                areaTreeVo.setChildren(getChildren(area.getId()));
                areaTreeVos.add(areaTreeVo);
            }
        }
        return areaTreeVos;
    }

    /**
     * 分页
     *
     * @param page
     * @param area
     * @return
     */
    @Override
    public IPage areaList(Page page, Area area) {
        long id = area.getParentId();
        LambdaQueryWrapper<Area> queryWrapper = new LambdaQueryWrapper<>();
        // 查询传入节点下的区域父id
        Set<Long> parentIdSet = getChildrenId(id);
        queryWrapper.eq(Area::getIsDelete, false);
        if (parentIdSet.size() > 0) {
            queryWrapper.in(Area::getParentId, parentIdSet);
            queryWrapper.or().eq(Area::getId, id);
        } else {
            queryWrapper.eq(Area::getId, id);
        }
        IPage pageArea = this.baseMapper.selectMapsPage(page, queryWrapper);

        // 查询平台区域数据字典
        FeignClientResult<List<DictionarieValueModel>> dictValues = Systemctl.dictionarieClient.dictValues(areaType);
        if (pageArea != null) {
            if (pageArea.getRecords() != null && pageArea.getRecords().size() > 0) {
                for (Object areas : pageArea.getRecords()) {
                    Map<String, Object> map = (Map<String, Object>) areas;
                    if (dictValues != null) {
                        List<DictionarieValueModel> values = dictValues.getResult();
                        // 根据区域类型查询子节点
                        if (values != null && values.size() > 0) {
                            for (DictionarieValueModel dictionarieValueModel : values) {
                                if (dictionarieValueModel.getDictDataKey().equals(map.get("type"))) {
                                    map.put("typeName", dictionarieValueModel.getDictDataValue());
                                }
                            }
                        }
                    }
                    List<SourceFile> sourceFiles = iSourceFileService.findBySourceId(Long.parseLong(String.valueOf(map.get("id"))));
                    map.put("files", sourceFiles);
                }
            }
        }
        return pageArea;
    }

    /**
     * 根据父节点查询所有子节点parentId
     *
     * @param parentId
     * @return
     */
    public Set<Long> getChildrenId(Long parentId) {
        Set<Long> idSet = new HashSet<>();
        LambdaQueryWrapper<Area> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Area::getParentId, parentId);
        queryWrapper.eq(Area::getIsDelete, false);
        List<Area> areas = this.baseMapper.selectList(queryWrapper);
        if (areas != null && areas.size() > 0) {
            for (Area area : areas) {
                idSet.add(area.getParentId());
                idSet.addAll(getChildrenId(area.getId()));
            }
        }
        return idSet;
    }

    @Override
    @Transactional
    public Object saveArea(AreaResquest areaResquest) {
        // 保存基础数据
        Area area = new Area();
        BeanUtils.copyProperties(areaResquest, area);
        boolean flag = this.save(area);
        // 保存图片
        long id = area.getId();
        if (areaResquest.getSourceFiles() != null) {
            iSourceFileService.saveSourceFile(id, areaResquest.getSourceFiles());
        }
        // 风险同步
        if (areaResquest.getRiskPointId() != null) {
            areaResquest.setId(id);
            SpringContextHolder.publishEvent(new SynAreaRiskEvent(this, areaResquest, AreaSynRiskOperator.ADD.getType()));
        }
        return flag;
    }

    @Override
    @Transactional
    public Object updateArea(AreaResquest areaResquest) {
        // 更新基础数据
        Area areaOld = this.baseMapper.selectById(areaResquest.getId());
        Area area = new Area();
        Bean.copyExistPropertis(areaResquest, area);
        boolean flag = this.updateById(area);
        // 保存图片
        long id = area.getId();
        if (areaResquest.getSourceFiles() != null) {
            iSourceFileService.saveSourceFile(id, areaResquest.getSourceFiles());
        }
        // 风险同步
        //第1种情况：之前未绑定，编辑时绑定
        if (areaOld.getRiskPointId() == null && areaResquest.getRiskPointId() != null) {
            SpringContextHolder.publishEvent(new SynAreaRiskEvent(this, areaResquest, AreaSynRiskOperator.UPDATE.getType()));
        }
        //第2种情况：之前已绑定，编辑时清除绑定
        if (areaOld.getRiskPointId() != null && areaResquest.getRiskPointId() == null) {
            areaResquest.setRiskPointId(areaOld.getRiskPointId());
            SpringContextHolder.publishEvent(new SynAreaRiskEvent(this, areaResquest, AreaSynRiskOperator.UPDATE.getType()));
        }
        //第3种情况：换绑
        if (areaOld.getRiskPointId() != null && areaResquest.getRiskPointId() != null && !areaOld.getRiskPointId().equals(areaResquest.getRiskPointId())) {
            SpringContextHolder.publishEvent(new SynAreaRiskEvent(this, areaResquest, AreaSynRiskOperator.UPDATE.getType()));
        }
        //第4种情况: 始终未绑定,不做任何操作
        if (areaOld.getRiskPointId() == null && areaResquest.getRiskPointId() == null) {
            return flag;
        }
        return flag;
    }

    @Override
    public int deleteArea(Long instanceId) {
        Area area = new Area();
        // 查询是否被引用
        LambdaQueryWrapper<EquipmentSpecific> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(EquipmentSpecific::getAreaId, instanceId);
        List<EquipmentSpecific> equipmentSpecificList = iEquipmentSpecificSerivce.list(queryWrapper);
        if (equipmentSpecificList != null && equipmentSpecificList.size() > 0) {
            return -1;
        } else {
            area.setIsDelete(true);
            area.setId(instanceId);
            return this.baseMapper.updateById(area);
        }
    }

    @Override
    public Map<String, Object> getById(Long instanceId) {
        Area area = this.baseMapper.selectById(instanceId);
        List<SourceFile> sourceFiles = iSourceFileService.findBySourceId(instanceId);
        Map<String, Object> map = new HashMap<>();
        map.put("area", area);
        map.put("files", sourceFiles);
        return map;
    }

    @Override
    @Transactional
    public List<AreaDto> getAreaTierTree(Integer tier) {
        List<AreaDto> list = areaMapper.findByIsDeleted(0);
        if (!CollectionUtils.isEmpty(list)) {
            return TreeNodeUtil.assembleTree(list, tier);
        }
        return Lists.newArrayList();
    }
}
