package com.bocloud.ims.service.resource;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.entity.enums.CloudProvider;
import com.bocloud.cmp.model.NetcardOperation;
import com.bocloud.common.model.*;
import com.bocloud.common.model.RequestContext.Catalog;
import com.bocloud.common.utils.*;
import com.bocloud.ims.entity.common.MathUtils;
import com.bocloud.ims.entity.common.TenantPool;
import com.bocloud.ims.entity.resource.*;
import com.bocloud.ims.entity.resource.PoolGroup.PriorityType;
import com.bocloud.ims.interfaces.check.ResourceCheckService;
import com.bocloud.ims.interfaces.resource.CloudServerService;
import com.bocloud.ims.interfaces.resource.DataStoreService;
import com.bocloud.ims.interfaces.resource.ResourcePoolService;
import com.bocloud.ims.interfaces.resource.ServerService;
import com.bocloud.ims.repository.resource.*;
import com.bocloud.ims.service.internal.SmsTenantService;
import com.bocloud.service.lock.BocloudACLock;
import com.bocloud.service.lock.LockFactory;
import com.google.api.client.util.Maps;
import org.apache.commons.lang3.StringUtils;
import org.apache.curator.shaded.com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 资源池
 *
 * @author wangyu
 * @version 1.0
 * @since 2020年6月23日
 */
@Service("poolGroupService") public class ResourcePoolServiceImpl implements ResourcePoolService {

    private final Logger logger = LoggerFactory.getLogger(VmResourcePoolServiceImpl.class);
    @Autowired private PoolGroupRepository poolGroupRepository;
    @Autowired private CloudServerRepository cloudServerRepository;
    @Autowired private LockFactory lockFactory;
    @Autowired private ResourceRepository resourceRepository;
    @Autowired private PoolGroupRelationRepository poolGroupRelationRepository;
    @Autowired private PoolGroupZoneRepository poolGroupZoneRepository;
    @Autowired private PortGroupRelationRepository portGroupRelationRepository;
    @Autowired private PoolGroupLabelRepository poolGroupLabelRepository;
    @Autowired private SchedulerPolicyRepository schedulerPolicyRepository;
    @Autowired private CloudVendorRepository vendorRepository;
    @Autowired private DictionaryRepository dictionaryRepository;
    @Autowired private SmsTenantService smsTenantService;
    @Autowired private ResourceCheckService resourceCheckService;
    @Autowired private CloudVendorRepository cloudVendorRepository;
    @Autowired private DataStoreRepository dataStoreRepository;
    @Autowired private ServerRepository serverRepository;
    @Autowired private ApplicationContext applicationContext;
    @Autowired private DataStoreService dataStoreService;
    @Autowired private StoreHostRepository storeHostRepository;
    @Autowired private CloudServerService cloudServerService;

    @Override public BocloudResult<GridBean<PoolGroup>> list(Pager pager, RequestContext context) {
        try {
            List<Param> params = Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>());
            Map<String, String> sorter = Optional.ofNullable(pager.getSorter()).orElse(Maps.newHashMap());
            Boolean simple = Optional.ofNullable(pager.getSimple()).orElse(false);
            sorter.put("gmtCreate", Common.ONE);
            Integer page = Optional.ofNullable(pager.getPage()).orElse(1);
            Integer rows = Optional.ofNullable(pager.getRows()).orElse(10);
            List<PoolGroup> list = null;
            int total = 0;
            GridBean gridBean = null;
            total = poolGroupRepository.count(params);
            if (simple) {
                List<SimpleBean> beans = poolGroupRepository.list(params, sorter);
                gridBean = new GridBean(1, 1, total, beans);
            } else {
                list = poolGroupRepository.list(page, rows, params, sorter);
                for (PoolGroup group : list) {
                    if (null != group.getIsPublic() && !group.getIsPublic()) {
                        String region = dictionaryRepository.getNameByValue(group.getRegion());
                        if (null != region) {
                            group.setRegionName(region);
                        }
                        String az = dictionaryRepository.getNameByValue(group.getAvailablitiyZone());
                        if (null != az) {
                            group.setAzName(az);
                        }
                    }
                }
                gridBean = GridHelper.getBean(page, rows, total, list);
            }
            return new BocloudResult<>(true, gridBean, "查询成功");
        } catch (Exception e) {
            logger.error("Get error message：{}", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    @Override public BocloudResult list(Long parentId, String category) {
        try {
            List<PoolGroup> poolGroup = getPoolGroupByPid(parentId, category);
            for (PoolGroup group : poolGroup) {
                String region = dictionaryRepository.getNameByValue(group.getRegion());
                if (null != region) {
                    group.setRegionName(region);
                }
                String az = dictionaryRepository.getNameByValue(group.getAvailablitiyZone());
                if (null != az) {
                    group.setAzName(az);
                }
            }
            return new BocloudResult<>(true, poolGroup, "查询资源池分组成功");
        } catch (Exception e) {
            logger.error("list poolGroup fail:", e);
            return new BocloudResult<>(false, "查询资源池分组失败");
        }
    }

    @Override public BocloudResult createReleation(PoolGroup group) {
        try {
            Assert.notNull(group, "参数格式错误");
            Long poolGroupId = group.getPoolGroupId();
            PoolGroup poolGroup = poolGroupRepository.query(poolGroupId);
            Assert.notNull(poolGroup, "资源池不存在");
            poolGroupRelationRepository.removeByPoolGroupId(poolGroupId);
            List<PoolGroupRelation> relations = group.getRelations();
            if (!ListTool.isEmpty(relations)) {
                for (PoolGroupRelation relation : relations) {
                    relation.setPoolGroupId(group.getId());
                    relation.setEnabled(true);
                    poolGroupRelationRepository.save(relation);
                }
            }
            return new BocloudResult<>(true, "绑定资源成功");
        } catch (Exception e) {
            logger.error("create releation fail :", e);
            return new BocloudResult<>(false, "绑定资源失败");
        }
    }

    @Override public BocloudResult removeReleation(PoolGroup poolGroupParam) {
        try {
            Assert.notNull(poolGroupParam, "参数格式有误");
            Long poolGroupId = poolGroupParam.getPoolGroupId();
            Long targetId = poolGroupParam.getTargetId();
            poolGroupRelationRepository.remove(poolGroupId, targetId);
            return new BocloudResult<>(true, "关联成功");
        } catch (Exception e) {
            logger.error("create releation fail :", e);
            return new BocloudResult<>(false, "关联失败：" + e.getMessage());
        }
    }

    /**
     * 查询可绑定的资源池列表
     */
    @Override public BocloudResult<List<PoolGroup>> listByCategory(String category) {
        try {
            List<PoolGroup> poolGroups = poolGroupRepository.listByCategory(category);
            List<PoolGroup> filterPools = Lists.newArrayList();
            for (PoolGroup poolGroup : poolGroups) {
                // 共享
                if (PoolGroup.BindingPolicy.share.name().equals(poolGroup.getBindingPolicy())) {
                    filterPools.add(poolGroup);
                }
            }
            return new BocloudResult<>(true, filterPools, "查询成功");
        } catch (Exception e) {
            logger.error("list poolGroup fail:", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    /**
     * 此方法递归使用,根据parentId查询子分组
     *
     * @param parentId
     * @return
     * @throws Exception
     */
    private List<PoolGroup> getPoolGroupByPid(Long parentId, String category) throws Exception {
        List<PoolGroup> poolGroups = poolGroupRepository.list(parentId, category);
        for (PoolGroup poolGroup : poolGroups) {
            if (null != poolGroup) {
                List<PoolGroup> children = getPoolGroupByPid(poolGroup.getId(), poolGroup.getCategory());
                if (null != children && !children.isEmpty()) {
                    poolGroup.setChildren("[]");
                    poolGroup.setChildrenList(children);
                }
            }
        }
        return poolGroups;
    }

    @Override public BocloudResult<PoolGroup> create(PoolGroup group) {
        try {
            BocloudResult result = exists(group.getName(), group.getCategory());
            Assert.isTrue(!result.isSuccess(), "此名称已存在!");
            List<PoolGroupRelation> relations = group.getRelations();
            CloudVendor vendor = vendorRepository.query(group.getVendorId());
            Assert.notNull(vendor, "云平台不存在");
            PoolGroup database =
                poolGroupRepository.getByRegion(group.getRegion(), group.getAvailablitiyZone(), vendor.getType());
            Assert.isNull(database, "当前可用区域下已绑定其他同类型云平台！");
            group.setIsPublic(vendor.getIsPublic());
            group.setVendorType(vendor.getType());
            if (StringUtils.isEmpty(group.getCategory())) {
                group.setCategory("COMPUTER");
            }
            this.poolGroupRepository.save(group);
            // 设置资源关联
            if (!StringUtils.isEmpty(group.getRelationType())) {
                if (!ListTool.isEmpty(relations)) {
                    for (PoolGroupRelation relation : relations) {
                        relation.setPoolGroupId(group.getId());
                        relation.setCategory(group.getRelationType());
                        relation.setEnabled(true);
                    }
                    List<DataStore> stores = new ArrayList<>();
                    List<Server> servers = new ArrayList<>();
                    List<Long> targetIds =
                        relations.stream().map(PoolGroupRelation::getTarget).collect(Collectors.toList());
                    StringBuilder idBuilder = new StringBuilder();
                    for (Long targetId : targetIds) {
                        idBuilder.append(targetId).append(",");
                    }
                    PoolGroup.RelationType type = PoolGroup.RelationType.valueOf(group.getRelationType());
                    switch (type) {
                        case Vdc:
                            List<DataStore> dataStores = dataStoreRepository.list(1, Integer.MAX_VALUE, Lists
                                .newArrayList(new Param(
                                    MapTools.simpleMap("vdcId", idBuilder.substring(0, idBuilder.length() - 1)),
                                    Sign.IN)), null);
                            if (!dataStores.isEmpty()) {
                                stores.addAll(dataStores);
                            }
                            List<Server> serverList = serverRepository.list(1, Integer.MAX_VALUE, Lists.newArrayList(
                                new Param(MapTools.simpleMap("vdcId", idBuilder.substring(0, idBuilder.length() - 1)),
                                    Sign.IN)), null, (String)null);
                            if (!serverList.isEmpty()) {
                                servers.addAll(serverList);
                            }
                            break;
                        case Cluster:
                            List<Server> clusterServerList = serverRepository.list(1, Integer.MAX_VALUE, Lists
                                .newArrayList(new Param(
                                    MapTools.simpleMap("clusterId", idBuilder.substring(0, idBuilder.length() - 1)),
                                    Sign.IN)), null, (String)null);
                            if (!clusterServerList.isEmpty()) {
                                servers.addAll(clusterServerList);
                            }
                            List<Long> serverIds =
                                clusterServerList.stream().map(Server::getId).collect(Collectors.toList());
                            List<DataStore> clusterDataStores = dataStoreRepository.listByServerIds(serverIds);
                            if (!clusterDataStores.isEmpty()) {
                                stores.addAll(clusterDataStores);
                            }
                            break;
                        case Host:
                            List<DataStore> hostDataStores = dataStoreRepository.listByServerIds(targetIds);
                            if (!hostDataStores.isEmpty()) {
                                stores.addAll(hostDataStores);
                            }
                            break;
                        default:
                            break;
                    }

                    if (!stores.isEmpty()) {
                        List<PoolGroupRelation> storageRelations = stores.stream().map(
                            store -> new PoolGroupRelation(null, group.getId(), store.getId(), "Storage", true, null,
                                null)).collect(Collectors.toList());
                        relations.addAll(storageRelations);
                    }
                    if (!servers.isEmpty()) {
                        List<PoolGroupRelation> storageRelations = servers.stream().map(
                            server -> new PoolGroupRelation(null, group.getId(), server.getId(), "Host", true, null,
                                null)).collect(Collectors.toList());
                        relations.addAll(storageRelations);
                    }
                    poolGroupRelationRepository.batchSave(relations, relations.size());
                }
            }
            // 设置网络关联
            List<PortGroupRelation> networkRelations = group.getNetworkRelations();
            if (!ListTool.isEmpty(networkRelations)) {
                for (PortGroupRelation networkRelation : networkRelations) {
                    networkRelation.setPoolGroupId(group.getId());
                }
                portGroupRelationRepository.batchSave(networkRelations, networkRelations.size());
            }
            // 设置地域关联
            List<PoolGroupZone> regionRelations = group.getRegionRelations();
            if (!ListTool.isEmpty(regionRelations)) {
                for (PoolGroupZone regionRelation : regionRelations) {
                    regionRelation.setPoolGroupId(group.getId());
                    regionRelation.setVendorId(group.getVendorId());
                    regionRelation.setChecked(true);
                }
                poolGroupZoneRepository.batchSave(regionRelations, regionRelations.size());
            }
            return new BocloudResult<>(true, group, "添加成功");
        } catch (Exception e) {
            logger.error("Create notice poolGroup error:", e);
            return new BocloudResult<>(false, "添加失败：" + e.getMessage());
        }
    }

    @Override public BocloudResult modify(PoolGroup bean, Long userId) {
        String path = VmResourcePool.class.getSimpleName() + "_" + bean.getId();
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            PoolGroup group = poolGroupRepository.query(bean.getId());
            Assert.notNull(group, "资源池分组不存在");
            BocloudResult bocloudResult = exists(bean.getName(), group.getCategory());
            if (bocloudResult.isSuccess()) {
                PoolGroup poolGroup = (PoolGroup)bocloudResult.getData();
                if (!poolGroup.getId().equals(group.getId())) {
                    return new BocloudResult<>(false, "此名称已存在!");
                }
            }
			CloudVendor cloudVendor = cloudVendorRepository.query(bean.getVendorId());
			if (null == cloudVendor) {
				return new BocloudResult<>(false, "云平台信息异常");
			}
			PoolGroup database = poolGroupRepository.getByRegion(bean.getRegion(), bean.getAvailablitiyZone(),
					cloudVendor.getType());
			if (null != database && database.getId() != group.getId()) {
				return new BocloudResult<>(false, "当前可用区域下已绑定其他同类型云平台！");
			}
            group.setVendorId(bean.getVendorId());
            group.setName(bean.getName());
            group.setRegion(bean.getRegion());
            group.setAvailablitiyZone(bean.getAvailablitiyZone());
            group.setBindingPolicy(bean.getBindingPolicy());
            group.setStatus(bean.getStatus());
            group.setPolicyId(bean.getPolicyId());
            group.setRemark(bean.getRemark());
            group.setMenderId(userId);
            group.setRelationType(bean.getRelationType());
            // 资源关联修改
            List<PoolGroupRelation> relations = bean.getRelations();
            poolGroupRelationRepository.removeByPoolGroupId(group.getId());
            if (!StringUtils.isEmpty(bean.getRelationType())) {
                if (!ListTool.isEmpty(relations)) {
                    for (PoolGroupRelation relation : relations) {
                        relation.setPoolGroupId(group.getId());
                        relation.setCategory(group.getRelationType());
                        relation.setEnabled(true);
                    }
                    List<DataStore> stores = new ArrayList<>();
                    List<Server> servers = new ArrayList<>();
                    List<Long> targetIds =
                        relations.stream().map(PoolGroupRelation::getTarget).collect(Collectors.toList());
                    StringBuilder idBuilder = new StringBuilder();
                    for (Long targetId : targetIds) {
                        idBuilder.append(targetId).append(",");
                    }
                    PoolGroup.RelationType type = PoolGroup.RelationType.valueOf(group.getRelationType());
                    switch (type) {
                        case Vdc:
                            List<DataStore> dataStores = dataStoreRepository.list(1, Integer.MAX_VALUE, Lists
                                .newArrayList(new Param(
                                    MapTools.simpleMap("vdcId", idBuilder.substring(0, idBuilder.length() - 1)),
                                    Sign.IN)), null);
                            if (!dataStores.isEmpty()) {
                                stores.addAll(dataStores);
                            }
                            List<Server> serverList = serverRepository.list(1, Integer.MAX_VALUE, Lists.newArrayList(
                                new Param(MapTools.simpleMap("vdcId", idBuilder.substring(0, idBuilder.length() - 1)),
                                    Sign.IN)), null, (String)null);
                            if (!serverList.isEmpty()) {
                                servers.addAll(serverList);
                            }
                            break;
                        case Cluster:
                            List<Server> clusterServerList = serverRepository.list(1, Integer.MAX_VALUE, Lists
                                .newArrayList(new Param(
                                    MapTools.simpleMap("clusterId", idBuilder.substring(0, idBuilder.length() - 1)),
                                    Sign.IN)), null, (String)null);
                            if (!clusterServerList.isEmpty()) {
                                servers.addAll(clusterServerList);
                            }
                            List<Long> serverIds =
                                clusterServerList.stream().map(Server::getId).collect(Collectors.toList());
                            List<DataStore> clusterDataStores = dataStoreRepository.listByServerIds(serverIds);
                            if (!clusterDataStores.isEmpty()) {
                                stores.addAll(clusterDataStores);
                            }
                            break;
                        case Host:
                            List<DataStore> hostDataStores = dataStoreRepository.listByServerIds(targetIds);
                            if (!hostDataStores.isEmpty()) {
                                stores.addAll(hostDataStores);
                            }
                            break;
                        default:
                            break;
                    }
                    if (!stores.isEmpty()) {
                        List<PoolGroupRelation> storageRelations = stores.stream().map(
                            store -> new PoolGroupRelation(null, group.getId(), store.getId(), "Storage", true, null,
                                null)).collect(Collectors.toList());
                        relations.addAll(storageRelations);
                    }
                    if (!servers.isEmpty()) {
                        List<PoolGroupRelation> storageRelations = servers.stream().map(
                            server -> new PoolGroupRelation(null, group.getId(), server.getId(), "Host", true, null,
                                null)).collect(Collectors.toList());
                        relations.addAll(storageRelations);
                    }
                    poolGroupRelationRepository.batchSave(relations, relations.size());
                }
            }
            // 网络关联修改
            portGroupRelationRepository.remove(group.getId());
            List<PortGroupRelation> networkRelations = bean.getNetworkRelations();
            if (!ListTool.isEmpty(networkRelations)) {
                for (PortGroupRelation networkRelation : networkRelations) {
                    networkRelation.setPoolGroupId(group.getId());
                }
                portGroupRelationRepository.batchSave(networkRelations, networkRelations.size());
            }
            // 设置地域关联
            poolGroupZoneRepository.remove(group.getId());
            List<PoolGroupZone> regionRelations = bean.getRegionRelations();
            if (!ListTool.isEmpty(regionRelations)) {
                for (PoolGroupZone regionRelation : regionRelations) {
                    regionRelation.setPoolGroupId(group.getId());
                    regionRelation.setVendorId(group.getVendorId());
                    regionRelation.setChecked(true);
                }
                poolGroupZoneRepository.batchSave(regionRelations, regionRelations.size());
            }
            Boolean result = poolGroupRepository.update(group);
            if (!result) {
                return new BocloudResult<>(false, "修改资源池分组失败");
            }
            return new BocloudResult<>(true, "修改成功");
        } catch (Exception e) {
            logger.error("Modify poolGroup fail:", e);
            return new BocloudResult<>(false, "修改失败： " + e.getMessage());
        }
    }

    @Override public BocloudResult remove(Long id, Long userId) {
        String path = PoolGroup.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            PoolGroup poolGroup = poolGroupRepository.query(id);
            if (null == poolGroup) {
                logger.warn("Pool Group not exists");
                return new BocloudResult<>(false, "资源池分组不存在");
            }
            List<PoolGroup> list = poolGroupRepository.list(id, poolGroup.getCategory());
            if (null != list && !list.isEmpty()) {
                return new BocloudResult<>(false, "资源池分组存在子分组，无法删除");
            }
            if ("Computer".equals(poolGroup.getCategory())) {
                List<Resource> resources = resourceRepository.queryByGroupId(id);
                if (!ListTool.isEmpty(resources)) {
                    return new BocloudResult<>(false, "资源分组下存在资源，无法删除");
                }
            }
            poolGroupRepository.delete(id, userId);
            poolGroupRelationRepository.remove(poolGroup.getId(), null);
            portGroupRelationRepository.remove(id);
            poolGroupZoneRepository.remove(id);
            poolGroupLabelRepository.removeByPoolGroupId(poolGroup.getId());
            return new BocloudResult<>(true, "删除成功");
        } catch (Exception e) {
            logger.error("Remove Pool Group fail:", e);
            return new BocloudResult<>(false, "删除失败");
        }

    }

    @Override public BocloudResult<PoolGroup> detail(Long id) {
        try {
            PoolGroup group = poolGroupRepository.query(id);
            String region = dictionaryRepository.getNameByValue(group.getRegion());
            if (null != region) {
                group.setRegionName(region);
            }
            String az = dictionaryRepository.getNameByValue(group.getAvailablitiyZone());
            if (null != az) {
                group.setAzName(az);
            }
            List<PoolGroupRelation> poolGroupRelations = poolGroupRelationRepository.listByGroupId(id);
            if (org.springframework.util.StringUtils.hasText(group.getRelationType())) {
                poolGroupRelations
                    .removeIf(poolGroupRelation -> !poolGroupRelation.getCategory().equals(group.getRelationType()));
            }
            group.setRelations(poolGroupRelations);
            List<PortGroupRelation> networkRelation = portGroupRelationRepository.listByGroupId(id);
            group.setNetworkRelations(networkRelation);
            List<PoolGroupZone> regionRelations =
                poolGroupZoneRepository.listByGroupId(group.getVendorId(), id, null, null);
            group.setRegionRelations(regionRelations);
            return new BocloudResult<>(true, group, "查询成功");
        } catch (Exception e) {
            logger.error("Query Pool Group fail:", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    @Override public BocloudResult exists(String name, String category) {
        try {
            PoolGroup group = poolGroupRepository.exists(name, category);
            if (null == group) {
                return new BocloudResult<>(false, "资源池分组不存在");
            }
            return new BocloudResult<>(true, group, "资源池分组存在");
        } catch (Exception e) {
            logger.error("get scriptGroup error:", e);
            return new BocloudResult<>(false, "资源池分组不存在");
        }
    }

    @Override public BocloudResult<List<PoolGroupLabel>> listPoolGroupLabel(String params) {
        try {
            JSONObject object = JSONTools.isJSONObj(params);
            if (null == object) {
                return new BocloudResult<>(false, "参数格式有误");
            }
            Long poolGroupId = object.getLong("poolGroupId");
            List<PoolGroupLabel> poolGroupLabels = poolGroupLabelRepository.listByGroupId(poolGroupId);
            return new BocloudResult<>(true, poolGroupLabels, "查询成功");
        } catch (Exception e) {
            logger.error("create label fail :", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    @Override @Transactional public BocloudResult createLabel(PoolGroup poolGroupParam) {
        try {
            if (null == poolGroupParam) {
                return new BocloudResult<>(false, "参数格式有误");
            }
            Long poolGroupId = poolGroupParam.getPoolGroupId();
            poolGroupLabelRepository.removeByPoolGroupId(poolGroupId);
            List<Long> labList = poolGroupParam.getLabelIds();
            PoolGroupLabel label = null;
            for (Long labId : labList) {
                label = new PoolGroupLabel();
                label.setPoolGroupId(poolGroupId);
                label.setLabelId(labId);
                poolGroupLabelRepository.save(label);
            }
            return new BocloudResult<>(true, "标签绑定成功");
        } catch (Exception e) {
            logger.error("create label fail :", e);
            return new BocloudResult<>(false, "标签绑定失败");
        }
    }

    @Override public BocloudResult removeLabel(PoolGroup poolGroupParam) {
        try {
            if (null == poolGroupParam) {
                return new BocloudResult<>(false, "参数格式有误");
            }
            Long poolGroupId = poolGroupParam.getPoolGroupId();
            Long labelId = poolGroupParam.getLabelId();
            poolGroupLabelRepository.remove(poolGroupId, labelId);
            return new BocloudResult<>(true, "标签删除成功");
        } catch (Exception e) {
            logger.error("create releation fail :", e);
            return new BocloudResult<>(false, "删除失败");
        }
    }

    /**
     * 查询业务绑定的资源池列表
     *
     * @param object
     * @return
     */
    @Override public BocloudResult<List<PoolGroup>> listByBusinessId(JSONObject object) {
        String category = object.getString("category");
        Long businessId = object.getLong("businessId");
        Long envId = object.getLong("envId");
        List<Long> labelIds = Lists.newArrayList();
        if (!StringUtils.isEmpty(object.getString("labelIds"))) {
            labelIds = JSONArray.parseArray(object.getString("labelIds"), Long.class);
        }
        try {
            List<PoolGroup> poolGroups = poolGroupRepository.list(category, businessId, envId, labelIds);
            return new BocloudResult<>(true, poolGroups, "查询成功");
        } catch (Exception e) {
            logger.error("list pool group fail :", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    @Override public BocloudResult<List<PoolGroupRelation>> listRelationByGroupId(JSONObject object) {
        try {
            Long poolGroupId = object.getLong("poolGroupId");
            String category = object.getString("category");
            List<PoolGroupRelation> list = poolGroupRelationRepository.list(poolGroupId, category);
            return new BocloudResult<>(true, list, "查询成功");
        } catch (Exception e) {
            logger.error("create releation fail :", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    /**
     * 查询业务绑定的资源池列表
     *
     * @param object
     * @return
     */
    @Override public BocloudResult<List<PoolGroup>> listByBidVid(JSONObject object, RequestContext context) {
        Long vendorId = object.getLong(Common.VENDORID);
        String category = object.getString("category");
        try {
            List<PoolGroup> poolGroups = poolGroupRepository.list(context.getTenant(), vendorId, category);
            return new BocloudResult<>(true, poolGroups, "查询成功");
        } catch (Exception e) {
            logger.error("list pool group fail :", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    @Override public BocloudResult groups(String params, RequestContext context) {
        JSONObject object = JSONTools.isJSONObj(params);
        String action = object.getString("condition");
        if (null == action && object.containsKey("parentId")) {
            Long parentId = object.getLong("parentId");
            String category = object.getString("category");
            Boolean assignTenant = object.getBoolean("assignTenant");
            BocloudResult result = this.list(parentId, category);
            if (null != assignTenant && assignTenant) {
                List<PoolGroup> poolGroup =
                    JSONArray.parseArray(JSONArray.toJSONString(result.getData()), PoolGroup.class);
                List<PoolGroup> newGroups = new ArrayList<>();
                for (PoolGroup group : poolGroup) {
                    if (PoolGroup.BindingPolicy.share.name().equalsIgnoreCase(group.getBindingPolicy())) {
                        newGroups.add(group);
                        continue;
                    }
                }
                result.setData(newGroups);
            }
            return result;
        }
        if ("listbybusinessid".equalsIgnoreCase(action)) { // 查询业务绑定的资源池列表
            return this.listByBusinessId(object);
        } else if ("listByBidVid".equalsIgnoreCase(action)) { // 根据业务平台ID查询资源池列表
            return this.listByBidVid(object, context);
        } else if ("listRelationByGroupId".equals(action)) { // 查询指定资源池下绑定的对象列表
            return this.listRelationByGroupId(object);
        } else if ("listbycategory".equalsIgnoreCase(action)) { // 查询可绑定的资源池列表
            String category = object.getString("category");
            return this.listByCategory(category);
        } else if ("listByTenantId".equalsIgnoreCase(action)) {
            try {
                Long tenantId = object.getLong("tenantId");
                Long envId = object.getLong("envId");
                String category = object.getString("category");
                List<Long> labelIds = Lists.newArrayList();
                Boolean assignTenant = object.getBoolean("assignTenant");
                if (!StringUtils.isEmpty(object.getString("labelIds"))) {
                    labelIds = JSONArray.parseArray(object.getString("labelIds"), Long.class);
                }
                List<PoolGroup> groups = poolGroupRepository
                    .listByTenantId(tenantId, category, labelIds, envId, object.getString("vendorType"));
                List<PoolGroup> newGroups = new ArrayList<>();
                for (PoolGroup group : groups) {
                    SchedulerPolicy policy = schedulerPolicyRepository.query(group.getPolicyId());
                    if (null != policy) {
                        group.setPolicyType(policy.getPolicy());
                    }
                    if (null != assignTenant && assignTenant) {
                        if (PoolGroup.BindingPolicy.share.name().equalsIgnoreCase(group.getBindingPolicy())) {
                            newGroups.add(group);
                            continue;
                        }
                    } else {
                        newGroups.add(group);
                    }
                }
                return new BocloudResult<>(true, newGroups, "查询成功");
            } catch (Exception e) {
                logger.error("Get error message：", e);
                return new BocloudResult<>(false, "查询失败");
            }
        } else {
            return ResultTools.formatErrResult();
        }
    }

    @Override public BocloudResult patch(Long id, Long policyId, String priorityType, RequestContext context) {
        String path = VmResourcePool.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            PoolGroup group = poolGroupRepository.query(id);
            if (null == group) {
                logger.warn("pool Group not exists");
                return new BocloudResult<>(false, "资源池分组不存在");
            }
            group.setPolicyId(policyId);
            if (!StringUtils.isEmpty(priorityType)) {
                group.setPriorityType(PriorityType.valueOf(priorityType));
            } else {
                group.setPriorityType(PriorityType.Cpu);
            }
            group.setMenderId(context.getTarget());
            Boolean result = poolGroupRepository.update(group);
            if (!result) {
                return new BocloudResult<>(false, "操作失败");
            }
            return new BocloudResult<>(true, "操作成功");
        } catch (Exception e) {
            logger.error("Modify poolGroup fail:", e);
            return new BocloudResult<>(false, "操作失败");
        }
    }

    @Override public BocloudResult condition(Pager pager, String condition, RequestContext context) {
        try {
            condition = Optional.ofNullable(condition).orElse("");
            JSONObject object = JSONObject.parseObject(condition);
            if ("getByAz".equalsIgnoreCase(object.getString("condition"))) {
                String region = object.getString("region");
                String az = object.getString("az");
                String vendorType = object.getString("vendorType");
                if (null == context.getTenant() || 0 == context.getTenant()) {
                    List<PoolGroup> groups = poolGroupRepository.getByRegion(region, az, vendorType, null);
                    if (ListTool.isEmpty(groups)) {
                        return new BocloudResult<>(false, "当前可用域未绑定任何资源池");
                    }
                    PoolGroup group = groups.get(0);
                    List<PoolGroupRelation> poolGroupRelations =
                        poolGroupRelationRepository.listByGroupId(group.getId());
                    if (org.springframework.util.StringUtils.hasText(group.getRelationType())) {
                        poolGroupRelations.removeIf(
                            poolGroupRelation -> !poolGroupRelation.getCategory().equals(group.getRelationType()));
                    }
                    group.setRelations(poolGroupRelations);
                    List<PortGroupRelation> networkRelation = portGroupRelationRepository.listByGroupId(group.getId());
                    group.setNetworkRelations(networkRelation);
                    List<PoolGroupZone> regionRelations =
                        poolGroupZoneRepository.listByGroupId(group.getVendorId(), group.getId(), null, null);
                    group.setRegionRelations(regionRelations);
                    return new BocloudResult<>(true, group, "查询成功");
                }
                List<TenantPool> pools = smsTenantService.listPoolByTenant(context.getTenant());
                if (ListTool.isEmpty(pools)) {
                    return new BocloudResult<>(false, "当前租户未绑定资源池");
                }
                List<Long> poolGroupIds = pools.stream().map(TenantPool::getPoolGroupId).collect(Collectors.toList());
                List<PoolGroup> groups = poolGroupRepository.getByRegion(region, az, vendorType, poolGroupIds);
                if (ListTool.isEmpty(groups)) {
                    return new BocloudResult<>(false, "租户绑定的资源池下不包含当前选择区域下的资源池");
                }
                PoolGroup group = groups.get(0);
                List<PoolGroupRelation> poolGroupRelations = poolGroupRelationRepository.listByGroupId(group.getId());
                if (org.springframework.util.StringUtils.hasText(group.getRelationType())) {
                    poolGroupRelations.removeIf(
                        poolGroupRelation -> !poolGroupRelation.getCategory().equals(group.getRelationType()));
                }
                group.setRelations(poolGroupRelations);
                List<PortGroupRelation> networkRelation = portGroupRelationRepository.listByGroupId(group.getId());
                group.setNetworkRelations(networkRelation);
                List<PoolGroupZone> regionRelations =
                    poolGroupZoneRepository.listByGroupId(group.getVendorId(), group.getId(), null, null);
                group.setRegionRelations(regionRelations);
                return new BocloudResult<>(true, group, "查询成功");
            } else if ("tenantCheck".equalsIgnoreCase(object.getString("condition"))) {
                List<Long> poolIds = JSONArray.parseArray(object.getString("poolIds"), Long.class);
                Long tenantId = object.getLong("tenantId");
                try {
                    for (Long poolId : poolIds) {
                        PoolGroup group = poolGroupRepository.query(poolId);
                        if (null != group) {
                            if ("COMPUTER".equalsIgnoreCase(group.getCategory())) {
                                BocloudResult result =
                                    resourceCheckService.vendorCheck(group.getName(), group.getVendorId(), tenantId);
                                if (result.isFailed()) {
                                    return result;
                                }
                            }
                        }
                    }
                    return new BocloudResult<>(true, "资源池移除校验通过");
                } catch (Exception e) {
                    logger.error("Get error message：", e);
                    return new BocloudResult<>(false, "资源池移除校验失败");
                }
            } else if ("listbybusinessid".equalsIgnoreCase(object.getString("condition"))) { // 查询业务绑定的资源池列表
                return this.listByBusinessId(object);
            } else if ("listByBidVid".equalsIgnoreCase(object.getString("condition"))) { // 根据业务平台ID查询资源池列表
                return this.listByBidVid(object, context);
            } else if ("listRelationByGroupId".equals(object.getString("condition"))) { // 查询指定资源池下绑定的对象列表
                return this.listRelationByGroupId(object);
            } else if ("listbycategory".equalsIgnoreCase(object.getString("condition"))) { // 查询可绑定的资源池列表
                String category = object.getString("category");
                return this.listByCategory(category);
            } else if ("listByTenantId".equalsIgnoreCase(object.getString("condition"))) {
                try {
                    Long tenantId = object.getLong("tenantId");
                    Long envId = object.getLong("envId");
                    String category = object.getString("category");
                    List<Long> labelIds = Lists.newArrayList();
                    Boolean assignTenant = object.getBoolean("assignTenant");
                    if (!StringUtils.isEmpty(object.getString("labelIds"))) {
                        labelIds = JSONArray.parseArray(object.getString("labelIds"), Long.class);
                    }
                    List<PoolGroup> groups = poolGroupRepository
                        .listByTenantId(tenantId, category, labelIds, envId, object.getString("vendorType"));
                    List<PoolGroup> newGroups = new ArrayList<>();
                    for (PoolGroup group : groups) {
                        SchedulerPolicy policy = schedulerPolicyRepository.query(group.getPolicyId());
                        if (null != policy) {
                            group.setPolicyType(policy.getPolicy());
                        }
                        if (null != assignTenant && assignTenant) {
                            if (PoolGroup.BindingPolicy.share.name().equalsIgnoreCase(group.getBindingPolicy())) {
                                newGroups.add(group);
                                continue;
                            }
                        } else {
                            newGroups.add(group);
                        }
                    }
                    return new BocloudResult<>(true, newGroups, "查询成功");
                } catch (Exception e) {
                    logger.error("Get error message：", e);
                    return new BocloudResult<>(false, "查询失败");
                }

            } else if ("listByVendorId".equalsIgnoreCase(object.getString("condition"))) {
                Long vendorId = object.getLong("vendorId");
                Long tenantId = object.getLong("tenantId");
                String regionId = object.getString("regionId");
                List<TenantPool> tenantPools = smsTenantService.listPoolByTenant(tenantId);
                if (ListTool.isEmpty(tenantPools)) {
                    return new BocloudResult<>(false, "未找到合适的资源池");
                }
                List<Long> poolIds = new ArrayList<>();
                tenantPools.forEach(tenantPool -> poolIds.add(tenantPool.getPoolGroupId()));
                List<PoolGroup> groups = poolGroupRepository.listByIds(poolIds);
                Stream<PoolGroup> filter = groups.stream().filter(group -> "COMPUTER".equals(group.getCategory()))
                    .filter(group -> group.getVendorId().equals(vendorId));
                if (!StringUtils.isEmpty(regionId)) {
                    filter = filter.filter(group -> regionId.equalsIgnoreCase(group.getRegion()));
                }
                PoolGroup findGroup = filter.findFirst().orElseThrow(() -> new Exception("未找到合适的资源池"));
                return new BocloudResult<>(true, findGroup, "查询成功");
            } else if ("listResources".equalsIgnoreCase(object.getString("condition"))) {
                return this.listResources(pager, condition, context);
            } else if ("listResourcesServers".equalsIgnoreCase(object.getString("condition"))) {
                return this.listResourcesServers(pager, condition, context);
            } else if ("listZonesByRegion".equalsIgnoreCase(object.getString("condition"))) {
                return this.listZonesByRegion(object, context);
            } else if ("listPoolGroups".equalsIgnoreCase(object.getString("condition"))) {
                List<Long> poolGroupIds = null;
                Long tenantId = object.getLong("tenantId");
                if (context.getCatalog().equals(Catalog.Tenant) || context.getCatalog().equals(Catalog.User) || null != tenantId) {
                    List<TenantPool> pools = smsTenantService.listPoolByTenant(tenantId == null ? context.getTenant() : tenantId);
                    if (ListTool.isEmpty(pools)) {
                        return new BocloudResult<>(false, "当前租户未绑定资源池");
                    }
                    poolGroupIds = pools.stream().map(TenantPool::getPoolGroupId).collect(Collectors.toList());
                }
                String vendorType = object.getString("vendorType");
                List<PoolGroup> groups = poolGroupRepository.getByRegion(null, null, vendorType, poolGroupIds);
                if (ListTool.isEmpty(groups)) {
                    return new BocloudResult<>(false, "租户绑定的资源池下暂无可用区域");
                }
                return new BocloudResult<>(true, groups, "查询成功");
            } else if ("listAssignGroups".equals(object.getString("condition"))) {
                List<PoolGroup> poolGroups = poolGroupRepository.listAll();
                List<PoolGroup> tenantExclusivePool = poolGroupRepository.listTenantPrivate();
                List<Long> exclusiveIds = tenantExclusivePool.stream().map(PoolGroup::getId).collect(Collectors.toList());
                poolGroups.removeIf(pool -> exclusiveIds.contains(pool.getId()));
                return new BocloudResult<>(true, poolGroups, "查询成功");
            }
            return new BocloudResult<>(false, "参数格式异常！");
        } catch (Exception e) {
            logger.error("资源池查询异常：" + e.getMessage());
            return new BocloudResult<>(false, "资源池查询异常：" + e.getMessage());
        }
    }

    private BocloudResult listResourcesServers(Pager pager, String condition, RequestContext context) {
        try {
            List<Param> params = Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>());
            Map<String, String> sorter = Optional.ofNullable(pager.getSorter()).orElse(Maps.newHashMap());
            sorter.put("gmtCreate", Common.ONE);
            Integer page = Optional.ofNullable(pager.getPage()).orElse(1);
            Integer rows = Optional.ofNullable(pager.getRows()).orElse(10);
            GridBean gridBean = GridHelper.getBean(page, rows, 0, new ArrayList<>());

            JSONObject object = JSON.parseObject(condition, JSONObject.class);
            Optional.ofNullable(object).orElseThrow(() -> new Exception("参数格式错误"));
            Long poolGroupId = object.getLong("poolGroupId");
            PoolGroup poolGroup = poolGroupRepository.query(poolGroupId);
            Assert.notNull(poolGroup, "资源池不存在");
            CloudVendor cloudVendor = cloudVendorRepository.query(poolGroup.getVendorId());
            Assert.notNull(cloudVendor, "资源池绑定的云平台不存在");
            Boolean isPublic = poolGroup.getIsPublic() == null ? false : poolGroup.getIsPublic();
            params.add(new Param(MapTools.simpleMap("vendorId", poolGroup.getVendorId()), Sign.EQ));
            if (isPublic) {
                params.add(new Param(MapTools.simpleMap("regionId", poolGroup.getRegion()), Sign.EQ));
                pager.setParams(params);
                return cloudServerService.list(pager, context);
            } else {
                CloudProvider cloudProvider = CloudProvider.valueOf(cloudVendor.getType());
                switch (cloudProvider) {
                    case OPENSTACK:
                        return cloudServerService.list(pager, context);
                    case VMWARE:
                        String relationType = poolGroup.getRelationType();
                        List<PoolGroupRelation> list =
                            poolGroupRelationRepository.list(poolGroupId, poolGroup.getRelationType());
                        if (ListTool.isEmpty(list)) {
                            return new BocloudResult(true, gridBean, "查询成功");
                        }
                        if ("Vdc".equalsIgnoreCase(relationType)) {
                            List<Long> targets =
                                list.stream().map(PoolGroupRelation::getTarget).collect(Collectors.toList());
                            params.add(new Param(MapTools.simpleMap("vdcId", this.generateHosts(targets)), Sign.IN));
                        } else if ("Host".equalsIgnoreCase(relationType)) {
                            List<Long> hostTargetIds =
                                list.stream().map(PoolGroupRelation::getTarget).collect(Collectors.toList());
                            params.add(
                                new Param(MapTools.simpleMap("hostId", this.generateHosts(hostTargetIds)), Sign.IN));
                        } else if ("Cluster".equalsIgnoreCase(relationType)) {
                            List<Long> clusterIds =
                                list.stream().map(PoolGroupRelation::getTarget).collect(Collectors.toList());
                            List<Server> listByClusters =
                                serverRepository.listByClusters(clusterIds, poolGroup.getVendorId());
                            List<Long> serverIds =
                                listByClusters.stream().map(Server::getId).collect(Collectors.toList());
                            params.add(new Param(MapTools.simpleMap("hostId", this.generateHosts(serverIds)), Sign.IN));
                        } else {
                            return new BocloudResult(true, gridBean, "查询成功");
                        }
                        params.add(new Param(MapTools.simpleMap("isTemplate", false), Sign.EQ));
                        pager.setParams(params);
                        return cloudServerService.list(pager, context);
                    default:
                        break;
                }
            }
            return new BocloudResult(true, gridBean, "查询成功");
        } catch (Exception e) {
            return new BocloudResult<>(false, "云资源查询失败：" + e.getMessage());
        }
    }

    @Override public List<PoolGroup> listTenantPoolGroups(Long tenantId, String vendorType) {
        List<PoolGroup> poolGroups = new ArrayList<>();
        try {
            List<TenantPool> pools = smsTenantService.listPoolByTenant(tenantId);
            if (ListTool.isEmpty(pools)) {
                return poolGroups;
            }
            List<Long> poolGroupIds = pools.stream().map(TenantPool::getPoolGroupId).collect(Collectors.toList());
            poolGroups = poolGroupRepository.listByIds(poolGroupIds, vendorType);
        } catch (Exception e) {
            logger.error("查询租户资源池异常：" + e.getMessage());
        }
        return poolGroups;
    }

    @Override public List<Long> listTenantVendorIds(Long tenantId, String vendorType) {
        List<Long> vendorIds = new ArrayList<>();
        try {
            List<PoolGroup> listTenantPoolGroups = listTenantPoolGroups(tenantId, vendorType);
            if (ListTool.isEmpty(listTenantPoolGroups)) {
                return vendorIds;
            }
            vendorIds = listTenantPoolGroups.stream().map(PoolGroup::getVendorId).collect(Collectors.toList());
        } catch (Exception e) {
            logger.error("根据资源池查询平台ID异常：" + e.getMessage());
        }
        return vendorIds;
    }

    private BocloudResult listZonesByRegion(JSONObject object, RequestContext context) {
        try {
            Long poolGroupId = object.getLong("poolGroupId");
            Long vendorId = object.getLong("vendorId");
            String regionId = object.getString("regionId");
            List<PoolGroupZone> listByGroupId =
                poolGroupZoneRepository.listByGroupId(vendorId, poolGroupId, regionId, null);
            listByGroupId.removeIf(poolGroupZone -> !poolGroupZone.getChecked());
            return new BocloudResult<>(true, listByGroupId, "查询成功");
        } catch (Exception e) {
            logger.error("create releation fail :", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }
    
    @Override public BocloudResult capacity(Long id) {
        try {
            PoolGroup poolGroup = poolGroupRepository.query(id);
            Optional.ofNullable(poolGroup).orElseThrow(() -> new Exception("资源池不存在"));
            Long vendorId = poolGroup.getVendorId();
            CloudVendor cloudVendor = cloudVendorRepository.query(vendorId);
            JSONObject result = new JSONObject();
            if (CloudProvider.valueOf(cloudVendor.getType()) == CloudProvider.VMWARE) {
                // 查询资源关联
                List<PoolGroupRelation> list = poolGroupRelationRepository.list(id, null);
                // 查询宿主机列表
                BocloudResult hostResult =
                    this.listHosts(list, poolGroup, new JSONObject(), new Pager(1, Integer.MAX_VALUE, null, null));
                GridBean gridBean =
                    JSONObject.parseObject(JSONObject.toJSONString(hostResult.getData()), GridBean.class);
                List<Server> servers = gridBean == null ? new ArrayList<>() :
                    Optional.ofNullable(JSONArray.parseArray(JSONObject.toJSONString(gridBean.getRows()), Server.class))
                        .orElse(new ArrayList<>());
                Integer cpuCore =
                    servers.stream().map(server -> server.getConfig() == null ? 0 : server.getConfig().getCpuCore())
                        .reduce(Integer::sum).orElse(0);
                Integer cpuAmount =
                    servers.stream().map(server -> server.getConfig() == null ? 0 : server.getConfig().getCpuAmount())
                        .reduce(Integer::sum).orElse(0);
                Long cpuHz =
                    servers.stream().map(server -> server.getConfig() == null ? 0 : server.getConfig().getCpuHz())
                        .reduce(Long::sum).orElse(0L);
                Double memory = servers.stream()
                    .map(server -> server.getConfig() == null ? 0 : server.getConfig().getMemoryCapacity())
                    .reduce(Double::sum).orElse(0D);
                Double memoryUsed =
                    servers.stream().map(server -> server.getConfig() == null ? 0 : server.getConfig().getMemUsed())
                        .reduce(Double::sum).orElse(0D);
                BocloudResult dataStoresData = this.listDataStores(list, poolGroup, new JSONObject(), new Pager(1, Integer.MAX_VALUE, null, null));
                GridBean dataStoreBeans = JSONObject.parseObject(JSONObject.toJSONString(dataStoresData.getData()), GridBean.class);
                List<DataStore> dataStores = dataStoreBeans == null ? new ArrayList<>() :
                    Optional.ofNullable(JSONArray.parseArray(JSONObject.toJSONString(dataStoreBeans.getRows()), DataStore.class))
                        .orElse(new ArrayList<>());
                Long disk = dataStores.stream().map(DataStore::getCapacity).reduce(Long::sum).orElse(0L);
                Long diskFree = dataStores.stream().map(DataStore::getFreeSpace).reduce(Long::sum).orElse(0L);
                Long diskUsed = disk-diskFree;
                Map<String, Object> params = MapTools.simpleMap("poolGroupId", id);
                params.put("isTemplate", false);
                List<CloudServer> cloudServers = cloudServerRepository
                    .list(1, Integer.MAX_VALUE, Lists.newArrayList(new Param(params, Sign.EQ)), null);
                Integer cpuDistribute =
                    cloudServers.stream().map(cloudServer -> Optional.ofNullable(cloudServer.getCpu()).orElse(0))
                        .reduce(Integer::sum).orElse(0);
                BigDecimal memDistribute = cloudServers.stream()
                    .map(cloudServer -> Optional.ofNullable(cloudServer.getMemory()).orElse(BigDecimal.ZERO))
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
                Integer diskDistribute =
                    cloudServers.stream().map(cloudServer -> Optional.ofNullable(cloudServer.getDisk()).orElse(0))
                        .reduce(Integer::sum).orElse(0);
                result.put("cpuCore", cpuCore);
                result.put("cpuAmount", cpuAmount);
                result.put("cpuHz", cpuHz);
                result.put("memory", MathUtils.round(memory, 2));
                result.put("memoryUsed", MathUtils.round(memoryUsed, 2));
                result.put("disk", MathUtils.round(disk, 2));
                result.put("diskUsed", MathUtils.round(diskUsed, 2));
                result.put("cpuDistribute", cpuDistribute);
                result.put("memDistribute", MathUtils.round(memDistribute.doubleValue(), 2));
                result.put("diskDistribute", diskDistribute);
                result.put("servers", cloudServers.size());
            }else if( CloudProvider.valueOf(cloudVendor.getType()) == CloudProvider.OPENSTACK){
                // 查询宿主机列表
                ServerService dispatchService = applicationContext.getBean("ServerService", ServerService.class);
                ArrayList<Param> pageParams =
                    Lists.newArrayList(new Param(MapTools.simpleMap("vendorId", poolGroup.getVendorId()), Sign.EQ));
                BocloudResult<GridBean> bocloudResult = dispatchService.list(new Pager(1, Integer.MAX_VALUE,pageParams , null));
                GridBean gridBean = bocloudResult.getData();
                List<Server> servers = gridBean == null ? new ArrayList<>() :
                    Optional.ofNullable(JSONArray.parseArray(JSONObject.toJSONString(gridBean.getRows()), Server.class))
                        .orElse(new ArrayList<>());
                Integer cpuCore =
                    servers.stream().map(server -> server.getConfig() == null ? 0 : server.getConfig().getCpuCore())
                        .reduce(Integer::sum).orElse(0);
                Integer cpuAmount =
                    servers.stream().map(server -> server.getConfig() == null ? 0 : server.getConfig().getCpuAmount())
                        .reduce(Integer::sum).orElse(0);
                Long cpuHz =
                    servers.stream().map(server -> server.getConfig() == null ? 0 : server.getConfig().getCpuHz())
                        .reduce(Long::sum).orElse(0L);
                Double memory = servers.stream()
                    .map(server -> server.getConfig() == null ? 0 : server.getConfig().getMemoryCapacity())
                    .reduce(Double::sum).orElse(0D);
                Double memoryUsed =
                    servers.stream().map(server -> server.getConfig() == null ? 0 : server.getConfig().getMemUsed())
                        .reduce(Double::sum).orElse(0D);
                Double disk = servers.stream()
                    .map(server -> server.getConfig() == null ? 0 : server.getConfig().getDiskCapacity())
                    .reduce(Double::sum).orElse(0D);
                Double diskUsed =
                    servers.stream().map(server -> server.getConfig() == null ? 0 : server.getConfig().getDiskUsed())
                        .reduce(Double::sum).orElse(0D);
                Map<String, Object> params = MapTools.simpleMap("poolGroupId", id);
                params.put("isTemplate", false);
                List<CloudServer> cloudServers = cloudServerRepository
                    .list(1, Integer.MAX_VALUE, Lists.newArrayList(new Param(params, Sign.EQ)), null);
                Integer cpuDistribute =
                    cloudServers.stream().map(cloudServer -> Optional.ofNullable(cloudServer.getCpu()).orElse(0))
                        .reduce(Integer::sum).orElse(0);
                BigDecimal memDistribute = cloudServers.stream()
                    .map(cloudServer -> Optional.ofNullable(cloudServer.getMemory()).orElse(BigDecimal.ZERO))
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
                Integer diskDistribute =
                    cloudServers.stream().map(cloudServer -> Optional.ofNullable(cloudServer.getDisk()).orElse(0))
                        .reduce(Integer::sum).orElse(0);
                result.put("cpuCore", cpuCore);
                result.put("cpuAmount", cpuAmount);
                result.put("cpuHz", cpuHz);
                result.put("memory", MathUtils.round(memory, 2));
                result.put("memoryUsed", MathUtils.round(memoryUsed, 2));
                result.put("disk", MathUtils.round(disk, 2));
                result.put("diskUsed", MathUtils.round(diskUsed, 2));
                result.put("cpuDistribute", cpuDistribute);
                result.put("memDistribute", MathUtils.round(memDistribute.doubleValue(), 2));
                result.put("diskDistribute", diskDistribute);
                result.put("servers", cloudServers.size());
            }
            return new BocloudResult(true, result, "查询成功");
        } catch (Exception e) {
            logger.error("get resource pool capacity info fail:", e);
            return new BocloudResult(false, "查询失败:" + e.getMessage());
        }
    }

    public BocloudResult listResources(Pager pager, String params, RequestContext context) {
        GridBean gridBean = GridHelper.getBean(1, 10, 0, new ArrayList<>());
        try {
            JSONObject object = JSON.parseObject(params, JSONObject.class);
            Optional.ofNullable(object).orElseThrow(() -> new Exception("参数格式错误"));
            Long poolGroupId = object.getLong("poolGroupId");
            String resourceCategory = object.getString("category");
            PoolGroup poolGroup = poolGroupRepository.query(poolGroupId);
            Optional.ofNullable(poolGroup).orElseThrow(() -> new Exception("资源池不存在"));
            Long vendorId = poolGroup.getVendorId();
            CloudVendor cloudVendor = cloudVendorRepository.query(vendorId);
            if (CloudProvider.valueOf(cloudVendor.getType()) == CloudProvider.VMWARE) {
                List<PoolGroupRelation> list =
                    poolGroupRelationRepository.list(poolGroupId, poolGroup.getRelationType());
                if (ListTool.isEmpty(list)) {
                    return new BocloudResult(true, gridBean, "查询成功");
                }
                // 查询宿主机列表
                if ("host".equalsIgnoreCase(resourceCategory)) {
                    return this.listHosts(list, poolGroup, object, pager);
                }
                // 查询数据存储
                if ("dataStore".equalsIgnoreCase(resourceCategory)) {
                    return this.listDataStores(list, poolGroup, object, pager);
                }
            }
            return new BocloudResult(true, gridBean, "查询成功");
        } catch (Exception e) {
            logger.error("Query vm list fail:", e);
            return new BocloudResult(false, "查询失败", null, null);
        }
    }

    private BocloudResult listDataStores(List<PoolGroupRelation> list, PoolGroup poolGroup, JSONObject object,
        Pager pager) {
        try {
            List<Param> param = Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>());
            String category = poolGroup.getRelationType();
            if ("Vdc".equalsIgnoreCase(category)) {
                List<Long> targets = list.stream().map(PoolGroupRelation::getTarget).collect(Collectors.toList());
                param.add(new Param(MapTools.simpleMap("vdcId", this.generateHosts(targets)), Sign.IN));
            } else if ("Host".equalsIgnoreCase(category)) {
                List<Long> hostTargetIds = list.stream().map(PoolGroupRelation::getTarget).collect(Collectors.toList());
                List<StoreHost> storeHosts = storeHostRepository.list(hostTargetIds, "PM", poolGroup.getVendorId());
                List<Long> storeIds = storeHosts.stream().map(StoreHost::getStoreId).collect(Collectors.toList());
                if (!ListTool.isEmpty(storeIds)) {
                    param.add(new Param(MapTools.simpleMap("id", this.generateHosts(storeIds)), Sign.IN));
                }
            } else if ("Cluster".equalsIgnoreCase(category)) {
                List<Long> clusterIds = list.stream().map(PoolGroupRelation::getTarget).collect(Collectors.toList());
                List<Server> listByClusters = serverRepository.listByClusters(clusterIds, poolGroup.getVendorId());
                List<Long> serverIds = listByClusters.stream().map(Server::getId).collect(Collectors.toList());
                List<StoreHost> storeHosts = storeHostRepository.list(serverIds, "PM", poolGroup.getVendorId());
                List<Long> storeIds = storeHosts.stream().map(StoreHost::getStoreId).collect(Collectors.toList());
                if (!ListTool.isEmpty(storeIds)) {
                    param.add(new Param(MapTools.simpleMap("id", this.generateHosts(storeIds)), Sign.IN));
                }
            } else {
                GridBean gridBean = GridHelper.getBean(pager.getPage(), pager.getRows(), 0, new ArrayList<>());
                return new BocloudResult(true, gridBean, "查询成功");
            }
            param.add(new Param(MapTools.simpleMap(Common.VENDORID, poolGroup.getVendorId()), Sign.EQ));
            String name = object.getString("name");
            if (!StringUtils.isEmpty(name)) {
                param.add(new Param(MapTools.simpleMap("name", name), Sign.LK));
            }
            pager.setParams(param);
            BocloudResult<GridBean<DataStore>> bocloudResult = dataStoreService.list(pager, null);
            if (bocloudResult.isSuccess() && null != bocloudResult.getData()) {
                List<DataStore> dataStores = bocloudResult.getData().getRows();
                if (!ListTool.isEmpty(dataStores)) {
                    for (DataStore dataStore : dataStores) {
                        PoolGroupRelation relation =
                            poolGroupRelationRepository.getByTarget(dataStore.getId(), "Storage", poolGroup.getId());
                        if (null != relation) {
                            dataStore.setEnabled(relation.getEnabled());
                        }
                    }
                }
            }
            return bocloudResult;
        } catch (Exception e) {
            logger.error("查询数据存储列表异常：" + e.getMessage());
            return new BocloudResult<>(false, "查询数据存储列表异常：" + e.getMessage());
        }
    }

    public BocloudResult listHosts(List<PoolGroupRelation> list, PoolGroup poolGroup, JSONObject object, Pager pager) {
        try {
            List<Param> param = Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>());
            String category = list.get(0).getCategory();
            List<Long> targets = list.stream().map(PoolGroupRelation::getTarget).collect(Collectors.toList());
            param.add(new Param(MapTools.simpleMap(Common.VENDORID, poolGroup.getVendorId()), Sign.EQ));
            if ("Host".equals(category)) {
                param.add(new Param(MapTools.simpleMap("id", this.generateHosts(targets)), Sign.IN));
            }
            if ("Cluster".equals(category)) {
                param.add(new Param(MapTools.simpleMap("clusterId", this.generateHosts(targets)), Sign.IN));
            }
            if ("Vdc".equals(category)) {
                param.add(new Param(MapTools.simpleMap("vdcId", this.generateHosts(targets)), Sign.IN));
            }
            String name = object.getString("name");
            if (!StringUtils.isEmpty(name)) {
                param.add(new Param(MapTools.simpleMap("name", name), Sign.LK));
            }
            ServerService dispatchService = applicationContext.getBean("ServerService", ServerService.class);
            pager.setParams(param);
            BocloudResult<GridBean> bocloudResult = dispatchService.list(pager);
            if (bocloudResult.isSuccess() && null != bocloudResult.getData()) {
                List<Server> serverList = bocloudResult.getData().getRows();
                if (!ListTool.isEmpty(serverList)) {
                    for (Server server : serverList) {
                        PoolGroupRelation relation =
                            poolGroupRelationRepository.getByTarget(server.getId(), "Host", poolGroup.getId());
                        if (null != relation) {
                            server.setEnabled(relation.getEnabled());
                        }
                    }
                }
            }
            return bocloudResult;
        } catch (Exception e) {
            logger.error("查询宿主机列表异常：" + e.getMessage());
            return new BocloudResult<>(false, "查询宿主机列表异常：" + e.getMessage());
        }
    }

    private Object generateHosts(List<Long> hostIds) {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < hostIds.size(); i++) {
            builder.append(hostIds.get(i)).append(",");
        }
        builder.append(" -1 ");
        return builder.toString();
    }

    @Override public BocloudResult updateStatus(List<Long> ids, String status, RequestContext context) {
        for (Long id : ids) {
            String path = PoolGroup.class.getSimpleName() + "_" + id;
            try (BocloudACLock lock = lockFactory.getACLock(path)) {
                Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
                poolGroupRepository.updateStatus(id, status, context.getTarget());
            } catch (Exception e) {
                logger.error("update pool group error," + e.getMessage());
                if ("NORMAL".equals(status)) {
                    return new BocloudResult<>(false, "资源池启用异常：" + e.getMessage());
                } else {
                    return new BocloudResult<>(false, "资源池禁用异常：" + e.getMessage());
                }
            }
        }
        if ("NORMAL".equals(status)) {
            return new BocloudResult<>(true, "资源池启用成功");
        } else {
            return new BocloudResult<>(true, "资源池禁用成功");
        }
    }

    @Override public BocloudResult enabled(PoolGroupRelation poolGroupRelation) {
        try {
            List<Long> targetIds = poolGroupRelation.getTargetIds();
            if (ListTool.isEmpty(targetIds)) {
                return new BocloudResult<>(false, "至少选择一条数据");
            }
            List<PoolGroupRelation> poolGroupRelations = new ArrayList<>();
            for (Long target : targetIds) {
                PoolGroupRelation groupRelation = poolGroupRelationRepository
                    .getByTarget(target, poolGroupRelation.getCategory(), poolGroupRelation.getPoolGroupId());
                if (null != groupRelation) {
                    groupRelation.setEnabled(poolGroupRelation.getEnabled());
                    poolGroupRelations.add(groupRelation);
                }
            }
            if (!ListTool.isEmpty(poolGroupRelations)) {
                poolGroupRelationRepository.batchUpdate(poolGroupRelations, poolGroupRelations.size());
            }
            return new BocloudResult(true, poolGroupRelation.getEnabled() ? "启用成功" : "禁用成功");
        } catch (Exception e) {
            logger.error("资源启用、禁用异常：" + e.getMessage());
            return new BocloudResult<>(false, "资源启用、禁用异常：" + e.getMessage());
        }
    }

    @Override public List<String> listTenantRegions(Long tenantId, String vendorType) {
        List<String> regions = new ArrayList<>();
        try {
            List<PoolGroup> listTenantPoolGroups = listTenantPoolGroups(tenantId, vendorType);
            if (ListTool.isEmpty(listTenantPoolGroups)) {
                return regions;
            }
            regions = listTenantPoolGroups.stream().map(PoolGroup::getRegion).collect(Collectors.toList());
        } catch (Exception e) {
            logger.error("根据资源池查询平台ID异常：" + e.getMessage());
        }
        return regions;
    }

    @Override
    public BocloudResult modifyRegionRelation(Long relationId, Boolean isUsed, RequestContext context) {
        try {
            PoolGroupZone poolGroupZone = poolGroupZoneRepository.query(relationId);
            if(null == poolGroupZone) {
                return new BocloudResult<>(false, "区域信息异常");
            }
            poolGroupZone.setChecked(isUsed);
            poolGroupZoneRepository.update(poolGroupZone);
            return new BocloudResult<>(true, "修改成功");
        } catch (Exception e) {
            logger.error("编辑区域可用、禁用异常 ：" + e.getMessage());
            return new BocloudResult<>(false, "编辑失败 ：" + e.getMessage());
        }
    }
}
