package com.bocloud.ims.service.resource.azure.network;

import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.network.NetworkInterfaceDriver;
import com.bocloud.cmp.model.NetworkInterfaceModel;
import com.bocloud.cmp.model.NotifyMessage;
import com.bocloud.cmp.model.azure.network.NicIpConfigurationModel;
import com.bocloud.cmp.params.azure.NicIpConfigurationOperationParams;
import com.bocloud.common.model.*;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.GridHelper;
import com.bocloud.common.utils.MapTools;
import com.bocloud.ims.common.enums.azure.AzureIpRelationType;
import com.bocloud.ims.common.enums.azure.AzureTaskStatus;
import com.bocloud.ims.entity.resource.*;
import com.bocloud.ims.entity.resource.azure.network.NicIpConfiguration;
import com.bocloud.ims.entity.resource.azure.network.PublicIPAddress;
import com.bocloud.ims.entity.resource.azure.network.ResourcePublicIPAddressRelation;
import com.bocloud.ims.interfaces.resource.azure.network.NicIpConfigurationService;
import com.bocloud.ims.repository.resource.*;
import com.bocloud.ims.repository.resource.azure.network.NicIpConfigurationRepository;
import com.bocloud.ims.repository.resource.azure.network.PublicIPAddressRepository;
import com.bocloud.ims.repository.resource.azure.network.ResourcePublicIPAddressRelationRepository;
import com.bocloud.ims.service.task.ResourceTaskNotice;
import com.bocloud.ims.service.utils.ResourceEventPublisher;
import com.bocloud.service.lock.BocloudACLock;
import com.bocloud.service.lock.LockFactory;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @Company: 博云 www.bocloud.com
 * @ClassName: NicIpConfigurationServiceImpl
 * @Description:
 * @author: zhenpingLi/李振平
 * @date: 2021/3/23 18:30
 */
@Service
public class NicIpConfigurationServiceImpl implements NicIpConfigurationService {

    private static Logger logger = LoggerFactory.getLogger(NicIpConfigurationServiceImpl.class);

    private static OperateResult.OperateCategory operateCategory = OperateResult.OperateCategory.ResourceEvent;

    @Autowired
    private CloudVendorRepository cloudVendorRepository;
    @Autowired
    private NetworkInterfaceRepository networkInterfaceRepository;
    @Autowired
    private LockFactory lockFactory;
    @Autowired
    private NetworkInterfaceDriver networkInterfaceDriver;
    @Autowired
    private VpcRepository vpcRepository;
    @Autowired
    private CloudServerRepository cloudServerRepository;
    @Autowired
    private SubnetRepository subnetRepository;
    @Autowired
    private ResourceEventPublisher resourceEventPublisher;
    @Autowired
    private ResourceEventRepository resourceEventRepository;
    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;
    @Autowired
    private PublicIPAddressRepository publicIPAddressRepository;
    @Autowired
    private ResourcePublicIPAddressRelationRepository resourcePublicIPAddressRelationRepository;
    @Autowired
    private AmqpTemplate amqpTemplate;
    @Autowired
    private NicIpConfigurationRepository nicIpConfigurationRepository;
    @Autowired
    private ResourceTaskNotice resourceTaskNotice;

    @Override
    public BocloudResult<Void> remove(Long id, RequestContext context) {
        String path = ResourceGroup.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");

            NicIpConfiguration nicIpConfiguration = nicIpConfigurationRepository.query(id);
            Assert.notNull(nicIpConfiguration, "资源不存在");
            NetworkInterface networkInterface = networkInterfaceRepository.query(nicIpConfiguration.getNetworkInterfaceId());
            Assert.notNull(networkInterface, "网络接口不存在");
            CloudVendor cloudVendor = cloudVendorRepository.query(networkInterface.getVendorId());
            Assert.notNull(cloudVendor, "平台不存在");
            PublicIPAddress publicIPAddress = publicIPAddressRepository.query(nicIpConfiguration.getPublicIpAddressId());

            NicIpConfigurationModel model = new NicIpConfigurationModel();
            model.setName(nicIpConfiguration.getName());
            model.setNetworkInterfaceUuid(networkInterface.getNetworkInterfaceUuid());
            taskExecutor.execute(() -> {
                String operate = cloudVendor.getType().toLowerCase() + ".networkInterface";
                String message = "网卡删除IP配置失败";
                BocloudResult result = networkInterfaceDriver.networkInterfaceRemoveNicIpConfiguration(cloudVendor.getUuid(), networkInterface.getRegionId(), model);
                try {
                    if (result.isSuccess()) {
                        message = "网卡删除IP配置成功";
                        nicIpConfigurationRepository.delete(id);
                        //公共IP重置状态删除公共IP和IP配置关系
                        if (!ObjectUtils.isEmpty(publicIPAddress)) {
                            //重置状态
                            publicIPAddress.setStatus(AzureTaskStatus.AVAILABLE.name());
                            publicIPAddressRepository.update(publicIPAddress);
                            resourcePublicIPAddressRelationRepository.removeByResourceId(id, AzureIpRelationType.NICIPCONFIGURATION.name());
                        }
                    } else {
                        logger.error("网卡删除IP配置失败：" + result.getMessage());
                        message = result.getMessage();
                    }
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", cloudVendor.getId()), operateCategory, context));
//                    //站内信推送
//                    NotifyMessage notifyMessage = new NotifyMessage(context, "提示:", message, null,
//                            true, false);
//                    amqpTemplate.convertAndSend("event.notice.queue", notifyMessage);
                } catch (Exception e) {
                    logger.error("networkInterface remove ipConfiguration fail:", e);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", cloudVendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult<>(true, "任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("networkInterface remove ipConfiguration fail:", e);
            return new BocloudResult<>(false, "网络接口删除IP配置失败 : " + e.getMessage());
        }
    }

    @Override
    public BocloudResult<GridBean<NicIpConfiguration>> list(Pager pager, RequestContext context) {
        try {
            GridBean gridBean;
            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);
            Integer page = Optional.ofNullable(pager.getPage()).orElse(1);
            Integer rows = Optional.ofNullable(pager.getRows()).orElse(10);
            int total = nicIpConfigurationRepository.count(params);
            List<NicIpConfiguration> list = this.nicIpConfigurationRepository.list(page, rows, params, sorter);
            gridBean = GridHelper.getBean(page, rows, total, list);
            return new BocloudResult<>(true, gridBean, "查询成功");
        } catch (Exception e) {
            logger.error("list nicIpConfiguration error!", e);
            return new BocloudResult<>(false, "查询失败:" + e.getMessage());
        }

    }

    @Override
    public BocloudResult<Void> create(NicIpConfiguration entity, RequestContext context) {
        try {
            Assert.notNull(entity, "参数格式不正确");

            NetworkInterface networkInterface = networkInterfaceRepository.query(entity.getNetworkInterfaceId());
            Assert.notNull(networkInterface, "网络接口不存在");
            CloudVendor cloudVendor = cloudVendorRepository.query(networkInterface.getVendorId());
            Assert.notNull(cloudVendor, "平台不存在");
            Vpc vpc = vpcRepository.query(networkInterface.getVpcId());
            Assert.notNull(vpc, "虚拟网络不存在");
            Subnet subnet = subnetRepository.query(networkInterface.getSubnetId());
            Assert.notNull(subnet, "子网不存在");
            PublicIPAddress publicIPAddress = publicIPAddressRepository.query(entity.getPublicIpAddressId());

            NicIpConfigurationModel model = new NicIpConfigurationModel();
            model.setName(entity.getName());
            model.setNetworkInterfaceUuid(networkInterface.getNetworkInterfaceUuid());
            model.setVpcUuid(vpc.getVpcId());
            model.setSubnetUuid(subnet.getSubnetUuid());
            if (!ObjectUtils.isEmpty(publicIPAddress)) {
                model.setPublicIpAddressUuid(publicIPAddress.getUuid());
            }

            taskExecutor.execute(() -> {
                String operate = cloudVendor.getType().toLowerCase() + ".networkInterface";
                String message = "网卡增加IP配置失败";
                BocloudResult result = networkInterfaceDriver.networkInterfaceAddNicIpConfiguration(cloudVendor.getUuid(), networkInterface.getRegionId(), model);
                try {
                    if (result.isSuccess()) {
                        message = "网卡增加IP配置成功";
                        NicIpConfigurationModel ipConfigurationModel = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), NicIpConfigurationModel.class);
                        entity.setUuid(ipConfigurationModel.getUuid());
                        entity.setVpcId(networkInterface.getVpcId());
                        entity.setSubnetId(networkInterface.getSubnetId());
                        entity.setIsPrimary(ipConfigurationModel.getIsPrimary());
                        entity.setName(ipConfigurationModel.getName());
                        entity.setPrivateIpAddress(ipConfigurationModel.getPrivateIpAddress());
                        entity.setIpMethod(ipConfigurationModel.getIpMethod());
                        if (!ObjectUtils.isEmpty(publicIPAddress)) {
                            entity.setPublicIpAddress(publicIPAddress.getIpAddress());
                        }
                        nicIpConfigurationRepository.save(entity);

                        //公共IP重置状态,增加公共IP和IP配置关系
                        if (!ObjectUtils.isEmpty(publicIPAddress)) {
                            //重置状态
                            publicIPAddress.setStatus(AzureTaskStatus.IN_USE.name());
                            publicIPAddressRepository.update(publicIPAddress);
                            ResourcePublicIPAddressRelation relation = new ResourcePublicIPAddressRelation();
                            relation.setIpId(publicIPAddress.getId());
                            relation.setResourceId(entity.getId());
                            relation.setResourceType(AzureIpRelationType.NICIPCONFIGURATION.name());
                            resourcePublicIPAddressRelationRepository.save(relation);
                        }

                    } else {
                        logger.error("网卡增加IP配置失败：" + result.getMessage());
                        message = result.getMessage();
                    }
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", cloudVendor.getId()), operateCategory, context));
//                    //站内信推送
//                    NotifyMessage notifyMessage = new NotifyMessage(context, "提示:", message, null,
//                            true, false);
//                    amqpTemplate.convertAndSend("event.notice.queue", notifyMessage);
                } catch (Exception e) {
                    logger.error("networkInterface add ipConfiguration fail:", e);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", cloudVendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult<>(true, "任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("networkInterface add ipConfiguration fail:", e);
            return new BocloudResult<>(false, "网络接口删除IP配置失败 : " + e.getMessage());
        }
    }

    @Override
    public BocloudResult<Void> modify(NicIpConfiguration modifyEntity, RequestContext context) {
        try {
            NicIpConfiguration entity = nicIpConfigurationRepository.query(modifyEntity.getId());
            Assert.notNull(entity, "资源找不到");
            NetworkInterface networkInterface = networkInterfaceRepository.query(entity.getNetworkInterfaceId());
            Assert.notNull(networkInterface, "网络接口找不到");
            CloudVendor cloudVendor = cloudVendorRepository.query(networkInterface.getVendorId());
            Assert.notNull(cloudVendor, "平台验证失败");

            NicIpConfigurationModel model = new NicIpConfigurationModel();
            model.setName(entity.getName());
            model.setNetworkInterfaceUuid(networkInterface.getNetworkInterfaceUuid());
            model.setIpMethod(modifyEntity.getIpMethod());
            model.setPrivateIpAddress(modifyEntity.getPrivateIpAddress());

            taskExecutor.execute(() -> {
                String operate = cloudVendor.getType().toLowerCase() + ".networkInterface";
                String message = "网卡修改IP配置失败";
                BocloudResult result = networkInterfaceDriver.networkInterfaceModifyNicIpConfiguration(cloudVendor.getUuid(), networkInterface.getRegionId(), model);
                try {
                    if (result.isSuccess()) {
                        message = "网卡修改IP配置成功";
                        NicIpConfigurationModel newModel = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), NicIpConfigurationModel.class);
                        entity.setPrivateIpAddress(newModel.getPrivateIpAddress());
                        entity.setIpMethod(newModel.getIpMethod());
                        nicIpConfigurationRepository.update(entity);

                    } else {
                        logger.error("网卡修改IP配置失败：" + result.getMessage());
                        message = result.getMessage();
                    }
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", cloudVendor.getId()), operateCategory, context));
//                    //站内信推送
//                    NotifyMessage notifyMessage = new NotifyMessage(context, "提示:", message, null,
//                            true, false);
//                    amqpTemplate.convertAndSend("event.notice.queue", notifyMessage);
                } catch (Exception e) {
                    logger.error("networkInterface modify ipConfiguration fail:", e);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", cloudVendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult<>(true, "任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("networkInterface modify ipConfiguration fail:", e);
            return new BocloudResult<>(false, "网络接口修改IP配置失败 : " + e.getMessage());
        }
    }

    @Override
    public BocloudResult<Void> operations(NicIpConfigurationOperationParams params, RequestContext context) {
        String action = params.getAction();
        //绑定弹性IP
        if ("attachPublicIp".equals(action)) {
            return this.attachPublicIpAddress(params, context);
        }
        if ("detachPublicIp".equals(action)) {
            return this.detachPublicIpAddress(params, context);
        }
        return new BocloudResult<>(false, "Unknown Operation！");
    }

    BocloudResult<Void> attachPublicIpAddress(NicIpConfigurationOperationParams params, RequestContext context) {
        Long publicIpAddressId = params.getPublicIpAddressId();
        try {
            NicIpConfiguration nicIpConfiguration = nicIpConfigurationRepository.query(params.getId());
            Assert.notNull(nicIpConfiguration, "数据不存在");
            NetworkInterface networkInterface = networkInterfaceRepository.query(nicIpConfiguration.getNetworkInterfaceId());
            Assert.notNull(networkInterface, "网络接口不存在");
            PublicIPAddress publicIPAddress = publicIPAddressRepository.query(publicIpAddressId);
            Assert.notNull(publicIPAddress, "弹性IP不存在");
            CloudVendor vendor = cloudVendorRepository.query(networkInterface.getVendorId());
            Assert.notNull(vendor, "平台验证失败");

            NicIpConfigurationModel model = new NicIpConfigurationModel();
            model.setName(nicIpConfiguration.getName());
            model.setPublicIpAddressUuid(publicIPAddress.getUuid());
            model.setNetworkInterfaceUuid(networkInterface.getNetworkInterfaceUuid());
            taskExecutor.execute(() -> {
                ResourceEvent event;
                String operate = vendor.getType().toLowerCase() + ".nics";
                String message = "附加弹性IP失败";
                BocloudResult result = networkInterfaceDriver.nicIpConfigurationAttachPublicIpAddress(vendor.getUuid(), networkInterface.getRegionId(), model);
                try {
                    if (result.isSuccess()) {
                        message = "附加弹性IP成功";
                        //第一步更新网络接口
                        NetworkInterfaceModel interfaceModel = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), NetworkInterfaceModel.class);
                        networkInterface.setMenderId(context.getTarget());
                        networkInterface.setGmtModify(new Date());
                        networkInterface.setPublicIPAddress(interfaceModel.getPublicIPAddress());
                        networkInterface.setPrimaryPrivateIPAddress(interfaceModel.getPrimaryPrivateIPAddress());
                        networkInterfaceRepository.update(networkInterface);
                        //第二步，更新网络接口下的IP配置
                        nicIpConfiguration.setPublicIpAddress(publicIPAddress.getIpAddress());
                        nicIpConfiguration.setPublicIpAddressId(publicIPAddress.getId());
                        nicIpConfigurationRepository.update(nicIpConfiguration);

                        //第三步 重置EIP状态
                        publicIPAddress.setStatus(AzureTaskStatus.IN_USE.name());
                        publicIPAddressRepository.update(publicIPAddress);

                        //第四步，更新EIP绑定关系
                        ResourcePublicIPAddressRelation relation = new ResourcePublicIPAddressRelation();
                        relation.setIpId(publicIPAddress.getId());
                        relation.setResourceId(nicIpConfiguration.getId());
                        relation.setResourceType(AzureIpRelationType.NICIPCONFIGURATION.name());
                        resourcePublicIPAddressRelationRepository.save(relation);

                        //第五步 更新云主机上的IP（只更新网卡的主IP配置信息）
                        if (null != networkInterface.getServerId()) {
                            //查询云主机绑定的所有网卡
                            List<NetworkInterface> networkInterfaces = networkInterfaceRepository.listByServerId(vendor.getId(), networkInterface.getServerId());
                            List<String> privateIps = networkInterfaces.stream().map(nfc -> nfc.getPrimaryPrivateIPAddress()).filter(privateIp -> null != privateIp).collect(Collectors.toList());
                            List<String> publicIps = networkInterfaces.stream().map(nfc -> nfc.getPublicIPAddress()).filter(publicIp -> null != publicIp).collect(Collectors.toList());
                            CloudServer cloudServer = cloudServerRepository.query(networkInterface.getServerId());
                            if (!ObjectUtils.isEmpty(cloudServer)) {
                                cloudServer.setPrivateIps(JSONObject.toJSONString(privateIps));
                                cloudServer.setPublicIps(JSONObject.toJSONString(publicIps));
                                cloudServer.setMenderId(context.getTarget());
                                cloudServer.setGmtModify(new Date());
                                cloudServerRepository.update(cloudServer);
                                //发送消息给cop
                                resourceTaskNotice.sendLogicalMessage(cloudServer, ResourceTaskNotice.Action.UPDATE);
                            }
                            event = new ResourceEvent(networkInterface.getServerId(), "绑定", "弹性IP 【" + publicIPAddress.getName()
                                    + "】绑定成功！云主机【" + cloudServer.getName() + "】", context.getTarget(), new Date(),
                                    "VM", vendor.getId(), context.getCatalog());
                            resourceEventRepository.save(event);
                        }
                        logger.info("网卡绑定弹性IP成功");
                    } else {
                        logger.error("附加弹性IP失败：" + result.getMessage());
                        message = result.getMessage();
                        if (null != networkInterface.getServerId()) {
                            CloudServer cloudServer = cloudServerRepository.query(networkInterface.getServerId());
                            event = new ResourceEvent(cloudServer.getId(), "绑定", "弹性IP 【" + publicIPAddress.getName()
                                    + "】绑定失败！云主机【" + cloudServer.getName() + "】", context.getTarget(), new Date(),
                                    "VM", vendor.getId(), context.getCatalog());
                            resourceEventRepository.save(event);
                        }
                        logger.info("网卡绑定弹性IP失败");
                    }
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                } catch (Exception e) {
                    logger.error("ipConfiguration attachPublicIpAddress fail:", e);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult<>(true, "附加弹性IP任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("ipConfiguration attachPublicIpAddress fail:", e);
            return new BocloudResult<>(false, "附加弹性IP失败 : " + e.getMessage());
        }
    }

    BocloudResult<Void> detachPublicIpAddress(NicIpConfigurationOperationParams params, RequestContext context) {
        try {
            NicIpConfiguration nicIpConfiguration = nicIpConfigurationRepository.query(params.getId());
            Assert.notNull(nicIpConfiguration, "数据不存在");
            PublicIPAddress publicIPAddress = publicIPAddressRepository.query(nicIpConfiguration.getPublicIpAddressId());
            Assert.notNull(publicIPAddress, "弹性IP不存在");
            NetworkInterface networkInterface = networkInterfaceRepository.query(nicIpConfiguration.getNetworkInterfaceId());
            Assert.notNull(networkInterface, "网络接口不存在");
            CloudVendor vendor = cloudVendorRepository.query(networkInterface.getVendorId());
            Assert.notNull(vendor, "平台验证失败");

            NicIpConfigurationModel model = new NicIpConfigurationModel();
            model.setNetworkInterfaceUuid(networkInterface.getNetworkInterfaceUuid());
            model.setName(nicIpConfiguration.getName());
            taskExecutor.execute(() -> {
                ResourceEvent event;
                String operate = vendor.getType().toLowerCase() + ".nics";
                String message = "解绑弹性IP失败";
                BocloudResult result = networkInterfaceDriver.nicIpConfigurationdetachPublicIpAddress(vendor.getUuid(), networkInterface.getRegionId(), model);
                try {
                    if (result.isSuccess()) {
                        message = "解绑弹性IP成功";
                        //第一步更新网络接口
                        NetworkInterfaceModel interfaceModel = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), NetworkInterfaceModel.class);
                        networkInterface.setMenderId(context.getTarget());
                        networkInterface.setGmtModify(new Date());
                        networkInterface.setPublicIPAddress(interfaceModel.getPublicIPAddress());
                        networkInterface.setPrimaryPrivateIPAddress(interfaceModel.getPrimaryPrivateIPAddress());
                        networkInterfaceRepository.update(networkInterface);

                        //第二步，更新网络接口下的IP配置
                        nicIpConfiguration.setPublicIpAddressId(null);
                        nicIpConfiguration.setPublicIpAddress(null);
                        nicIpConfigurationRepository.update(nicIpConfiguration);

                        //第三步 重置EIP状态
                        publicIPAddress.setStatus(AzureTaskStatus.AVAILABLE.name());
                        publicIPAddressRepository.update(publicIPAddress);

                        //第四步，更新EIP绑定关系
                        resourcePublicIPAddressRelationRepository.removeByResourceId(nicIpConfiguration.getId(), AzureIpRelationType.NICIPCONFIGURATION.name());

                        //第五步 更新云主机上的IP（只更新网卡的主IP配置信息）
                        if (null != networkInterface.getServerId()) {
                            //查询云主机绑定的所有网卡
                            List<NetworkInterface> networkInterfaces = networkInterfaceRepository.listByServerId(vendor.getId(), networkInterface.getServerId());
                            List<String> privateIps = networkInterfaces.stream().map(nfc -> nfc.getPrimaryPrivateIPAddress()).filter(privateIp -> null != privateIp).collect(Collectors.toList());
                            List<String> publicIps = networkInterfaces.stream().map(nfc -> nfc.getPublicIPAddress()).filter(publicIp -> null != publicIp).collect(Collectors.toList());
                            CloudServer cloudServer = cloudServerRepository.query(networkInterface.getServerId());
                            if (!ObjectUtils.isEmpty(cloudServer)) {
                                cloudServer.setPrivateIps(JSONObject.toJSONString(privateIps));
                                if (CollectionUtils.isEmpty(publicIps)) {
                                    cloudServer.setPublicIps(null);
                                } else {
                                    cloudServer.setPublicIps(JSONObject.toJSONString(publicIps));
                                }
                                cloudServer.setMenderId(context.getTarget());
                                cloudServer.setGmtModify(new Date());
                                cloudServerRepository.update(cloudServer);
                                //发送消息给cop
                                resourceTaskNotice.sendLogicalMessage(cloudServer, ResourceTaskNotice.Action.UPDATE);
                            }
                            event = new ResourceEvent(networkInterface.getServerId(), "分离", "弹性IP分离成功！云主机【" + cloudServer.getName() + "】", context.getTarget(), new Date(),
                                    "VM", vendor.getId(), context.getCatalog());
                            resourceEventRepository.save(event);
                        }
                        logger.info("网络接口解绑弹性IP成功！");
                    } else {
                        logger.error("解绑弹性IP失败：" + result.getMessage());
                        message = result.getMessage();
                        if (null != networkInterface.getServerId()) {
                            CloudServer cloudServer = cloudServerRepository.query(networkInterface.getServerId());
                            event = new ResourceEvent(networkInterface.getServerId(), "分离", "弹性IP分离失败！云主机【" + cloudServer.getName() + "】", context.getTarget(), new Date(),
                                    "VM", vendor.getId(), context.getCatalog());
                            resourceEventRepository.save(event);
                        }
                        logger.info("网络接口解绑弹性IP失败！");
                    }
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                } catch (Exception e) {
                    logger.info("网络接口解绑弹性IP失败！");
                    logger.error("ipConfiguration detachPublicIpAddress fail:", e);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult<>(true, "解绑弹性IP任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("ipConfiguration detachPublicIpAddress fail:", e);
            return new BocloudResult<>(false, "解绑弹性IP失败 : " + e.getMessage());
        }
    }


    @Override
    public BocloudResult<Void> detachPublicIpAddress(Long id, RequestContext context) {
        try {
            NicIpConfiguration nicIpConfiguration = nicIpConfigurationRepository.query(id);
            Assert.notNull(nicIpConfiguration, "资源不存在");
            PublicIPAddress publicIPAddress = publicIPAddressRepository.query(nicIpConfiguration.getPublicIpAddressId());
            Assert.notNull(publicIPAddress, "公共IP地址不存在");
            NetworkInterface networkInterface = networkInterfaceRepository.query(nicIpConfiguration.getNetworkInterfaceId());
            Assert.notNull(networkInterface, "网络接口不存在");
            CloudVendor vendor = cloudVendorRepository.query(networkInterface.getVendorId());
            Assert.notNull(vendor, "平台不存在");
            NicIpConfigurationModel model = new NicIpConfigurationModel();
            model.setNetworkInterfaceUuid(networkInterface.getNetworkInterfaceUuid());
            model.setName(nicIpConfiguration.getName());
            BocloudResult result = networkInterfaceDriver.nicIpConfigurationdetachPublicIpAddress(vendor.getUuid(), networkInterface.getRegionId(), model);
            if (result.isSuccess()) {
                //第一步更新网络接口
                NetworkInterfaceModel interfaceModel = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), NetworkInterfaceModel.class);
                networkInterface.setMenderId(context.getTarget());
                networkInterface.setGmtModify(new Date());
                networkInterface.setPublicIPAddress(interfaceModel.getPublicIPAddress());
                networkInterface.setPrimaryPrivateIPAddress(interfaceModel.getPrimaryPrivateIPAddress());
                networkInterfaceRepository.update(networkInterface);

                //第二步，更新网络接口下的IP配置
                nicIpConfiguration.setPublicIpAddressId(null);
                nicIpConfiguration.setPublicIpAddress(null);
                nicIpConfigurationRepository.update(nicIpConfiguration);

                //第三步 重置EIP状态
                publicIPAddress.setStatus(AzureTaskStatus.AVAILABLE.name());
                publicIPAddressRepository.update(publicIPAddress);

                //第四步，更新EIP绑定关系
                resourcePublicIPAddressRelationRepository.removeByResourceId(nicIpConfiguration.getId(), AzureIpRelationType.NICIPCONFIGURATION.name());

                //第五步 更新云主机上的IP（只更新网卡的主IP配置信息）
                if (null != networkInterface.getServerId()) {
                    //查询云主机绑定的所有网卡
                    List<NetworkInterface> networkInterfaces = networkInterfaceRepository.listByServerId(vendor.getId(), networkInterface.getServerId());
                    List<String> privateIps = networkInterfaces.stream().map(nfc -> nfc.getPrimaryPrivateIPAddress()).filter(privateIp -> null != privateIp).collect(Collectors.toList());
                    List<String> publicIps = networkInterfaces.stream().map(nfc -> nfc.getPublicIPAddress()).filter(publicIp -> null != publicIp).collect(Collectors.toList());
                    CloudServer cloudServer = cloudServerRepository.query(networkInterface.getServerId());
                    if (!ObjectUtils.isEmpty(cloudServer)) {
                        cloudServer.setPrivateIps(JSONObject.toJSONString(privateIps));
                        if (CollectionUtils.isEmpty(publicIps)) {
                            cloudServer.setPublicIps(null);
                        } else {
                            cloudServer.setPublicIps(JSONObject.toJSONString(publicIps));
                        }
                        cloudServer.setMenderId(context.getTarget());
                        cloudServer.setGmtModify(new Date());
                        cloudServerRepository.update(cloudServer);
                        //发送消息给cop
                        resourceTaskNotice.sendLogicalMessage(cloudServer, ResourceTaskNotice.Action.UPDATE);
                    }
                }
                logger.info("IP配置解绑弹性IP成功！");
            } else {
                logger.info("IP配置解绑弹性IP成功！");
            }
            return new BocloudResult<>(true, "解绑弹性IP成功");
        } catch (Exception e) {
            logger.error("ipConfiguration detachPublicIpAddress fail:", e);
            return new BocloudResult<>(false, "解绑弹性IP失败 : " + e.getMessage());
        }
    }

}