package com.bocloud.ims.service.resource;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.network.ElasticIpDriver;
import com.bocloud.cmp.driver.network.NatGatewayDriver;
import com.bocloud.cmp.driver.network.NetworkInterfaceDriver;
import com.bocloud.cmp.entity.enums.CloudProvider;
import com.bocloud.cmp.entity.enums.InstanceType;
import com.bocloud.cmp.model.ElasticIpModel;
import com.bocloud.cmp.model.NatGatewayModel;
import com.bocloud.cmp.model.NetworkInterfaceModel;
import com.bocloud.cmp.model.PortModel;
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.entity.resource.*;
import com.bocloud.ims.interfaces.resource.NatGatewayService;
import com.bocloud.ims.repository.resource.*;
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.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

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

@Service("natGatewayService")
public class NatGatewayServiceImpl implements NatGatewayService {
    private static Logger logger = LoggerFactory.getLogger(NatGatewayServiceImpl.class);
    @Autowired
    private NatGatewayRepository natGatewayRepository;
    @Autowired
    private CloudVendorRepository cloudVendorRepository;
    @Autowired
    private VpcRepository vpcRepository;
    @Autowired
    private SubnetRepository subnetRepository;
    @Autowired
    private NatGatewayDnatRuleRepository dnatRuleRepository;
    @Autowired
    private NatGatewaySnatRuleRepository snatRuleRepository;
    @Autowired
    private ElasticIpRepository elasticIpRepository;
    @Autowired
    private NatGatewayDriver natGatewayDriver;
    @Autowired
    private ElasticIpDriver elasticIpDriver;
    @Autowired
    private NetworkInterfaceDriver networkInterfaceDriver;
    @Autowired
    private LockFactory lockFactory;
    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;
    @Autowired
    private ResourceEventPublisher resourceEventPublisher;
    @Autowired
    private NetworkInterfaceRepository networkInterfaceRepository;
    @Autowired
    private RouteTableRepository routeTableRepository;
    @Autowired
    private NatGatewayDnatRuleRepository natGatewayDnatRuleRepository;
    @Autowired
    private NatGatewaySnatRuleRepository natGatewaySnatRuleRepository;
    @Autowired
    private PortRepository portRepository;

    @Override
    public BocloudResult<GridBean<NatGateway>> 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());
            sorter.put("gmtCreate", Common.ONE);
            Integer page = Optional.ofNullable(pager.getPage()).orElse(1);
            Integer rows = Optional.ofNullable(pager.getRows()).orElse(10);

            int total = natGatewayRepository.count(params);
            List<NatGateway> list = natGatewayRepository.list(page, rows, params, sorter);
            GridBean<NatGateway> gridBean = GridHelper.getBean(page, rows, total, list);
            return new BocloudResult<GridBean<NatGateway>>(true, gridBean, "查询成功");
        } catch (Exception e) {
            logger.error("list natGateway failure:", e);
            return new BocloudResult<GridBean<NatGateway>>(false, "查询失败", null, null);
        }
    }

    @Override
    public BocloudResult<NatGateway> create(NatGateway natGateway, RequestContext context) {
        try {
            CloudVendor vendor = cloudVendorRepository.query(natGateway.getVendorId());
            if (null == vendor) {
                return new BocloudResult<NatGateway>(false, "云平台不存在");
            }
            if (null != natGatewayRepository.exists(natGateway.getName(), natGateway.getRegionId())) {
                return new BocloudResult<NatGateway>(false, "nat网关名称已存在");
            }
            Subnet subnet = subnetRepository.query(natGateway.getSubnetId());
            if (null == subnet) {
                return new BocloudResult<NatGateway>(false, "未找到子网");
            }
            Long vpcId = natGateway.getVpcId() != null ? natGateway.getVpcId() : subnet.getVpcId();
            Vpc vpc = vpcRepository.query(vpcId);
            if (null == vpc) {
                return new BocloudResult<NatGateway>(false, "未找到vpc");
            }

            CloudProvider provider = CloudProvider.valueOf(vendor.getType());
            NatGatewayModel natGatewayModel = new NatGatewayModel();
            final NatGateway finalNatGateway = natGateway;
            switch (provider) {
                case ALIYUN:
                    BeanUtils.copyProperties(natGateway, natGatewayModel);
                    natGatewayModel.setVpcUuid(vpc.getVpcId());
                    natGatewayModel.setSubnetUuid(subnet.getSubnetUuid());
                    natGatewayModel.setType("Enhanced");// 暂默认增强型
                    new Thread(() -> {
                        String operate = vendor.getType().toLowerCase() + ".natGateway";
                        String content = "NAT网关创建失败";
                        BocloudResult bocloudResult = null;
                        try {
                            bocloudResult = natGatewayDriver.create(natGatewayModel, vendor.getUuid(),
                                finalNatGateway.getRegionId());
                            if (bocloudResult.isSuccess()) {
                                NatGatewayModel gatewayModel = JSONObject.parseObject(
                                    JSONObject.toJSONString(bocloudResult.getData()), NatGatewayModel.class);
                                BeanUtils.copyProperties(gatewayModel, finalNatGateway);
                                finalNatGateway.setVendorId(vendor.getId());
                                finalNatGateway.setRegionId(natGatewayModel.getRegionId());
                                finalNatGateway.setCreatorId(context.getTarget());
                                natGatewayRepository.save(finalNatGateway);
                                // 新增弹性网卡(增强型网关会自动创建弹性网卡)
                                if (null != gatewayModel.getNetworkInterfaceModel()) {
                                    NetworkInterfaceModel networkInterfaceModel =
                                        gatewayModel.getNetworkInterfaceModel();
                                    NetworkInterface networkInterface = new NetworkInterface();
                                    BeanUtils.copyProperties(networkInterfaceModel, networkInterface);
                                    networkInterface.setVpcId(vpc.getId());
                                    networkInterface.setVendorId(vendor.getId());
                                    networkInterface.setCreatorId(context.getTarget());
                                    networkInterface.setGmtCreate(new Date());
                                    networkInterface.setTenantId(context.getTenant());
                                    networkInterface.setRegionId(finalNatGateway.getRegionId());
                                    networkInterface.setZone(subnet.getZone());
                                    networkInterface.setProjectId(context.getProject());
                                    networkInterface.setSubnetName(subnet.getName());
                                    networkInterface.setSubnetId(subnet.getId());
                                    networkInterface.setResourceGroupUuid(finalNatGateway.getResourceGroupUuid());
                                    networkInterface.setSgroupUuid(
                                        JSONObject.toJSONString(networkInterfaceModel.getSecurityGroups()));
                                    networkInterface.setNatGatewayUuid(gatewayModel.getUuid());
                                    networkInterfaceRepository.save(networkInterface);
                                }
                                content = "NAT网关创建成功";
                            } else {
                                content = bocloudResult.getMessage();
                            }
                        } catch (Exception e) {
                            logger.error("Get error message:", e);
                            content = e.getMessage();
                        }
                        resourceEventPublisher.send(new OperateResult(bocloudResult.isSuccess(), content, operate,
                            MapTools.simpleMap(Common.VENDORID, vendor.getId()),
                            OperateResult.OperateCategory.ResourceEvent, context));
                    }).start();
                    return new BocloudResult<>(true, "NAT网关创建任务已经下发，正在执行...");
                case HUAWEI:
                    BeanUtils.copyProperties(natGateway, natGatewayModel);
                    natGatewayModel.setVpcUuid(vpc.getVpcId());
                    natGatewayModel.setSubnetUuid(subnet.getSubnetUuid());
                    taskExecutor.submit(() -> {
                        OperateResult result = new OperateResult(true, "", "huawei.createNatGateway", null,
                            OperateResult.OperateCategory.ResourceEvent, context);
                        BocloudResult createResult =
                            natGatewayDriver.create(natGatewayModel, vendor.getUuid(), finalNatGateway.getRegionId());
                        if (createResult.isFailed()) {
                            result.setSuccess(false);
                            result.setMessage("创建nat网关失败：" + createResult.getMessage());
                            resourceEventPublisher.send(result);
                            return;
                        }

                        NatGatewayModel gatewayModel = JSONObject
                            .parseObject(JSONObject.toJSONString(createResult.getData()), NatGatewayModel.class);
                        PortModel portModel = gatewayModel.getPortModel();
                        BeanUtils.copyProperties(gatewayModel, finalNatGateway);
                        finalNatGateway.setCreatorId(context.getTarget());
                        finalNatGateway.setGmtCreate(gatewayModel.getGmtCreate());
                        finalNatGateway.setVendorId(vendor.getId());
                        finalNatGateway.setVpcId(vpc.getId());
                        finalNatGateway.setSubnetId(subnet.getId());
                        natGatewayRepository.save(finalNatGateway);
                        if (null != portModel) {
                            Port port = new Port();
                            BeanUtils.copyProperties(portModel, port);
                            port.setCreatorId(context.getTarget());
                            port.setRegionId(finalNatGateway.getRegionId());
                            port.setGmtCreate(new Date());
                            port.setVendorId(finalNatGateway.getVendorId());
                            portRepository.save(port);
                        }
                        result.setSuccess(true);
                        result.setMessage("创建nat网关[" + natGatewayModel.getName() + "]成功");
                        resourceEventPublisher.send(result);
                        return;
                    });
                    return new BocloudResult<>(true, "任务已经下发，正在执行...");
                case AWS:
                    ElasticIp elasticIp = elasticIpRepository.query(natGateway.getEipId());
                    if (null == elasticIp) {
                        return new BocloudResult<>(false, "未找到elasticIp");
                    }
                    BeanUtils.copyProperties(natGateway, natGatewayModel);
                    natGatewayModel.setAllocationUuid(elasticIp.getElasticIpUuid());
                    natGatewayModel.setSubnetUuid(subnet.getSubnetUuid());
                    taskExecutor.submit(() -> {
                        OperateResult result = new OperateResult(true, "", "aws.createNatGateway", null,
                            OperateResult.OperateCategory.ResourceEvent, context);
                        BocloudResult createResult =
                            natGatewayDriver.create(natGatewayModel, vendor.getUuid(), finalNatGateway.getRegionId());
                        if (createResult.isFailed()) {
                            result.setSuccess(false);
                            result.setMessage("创建nat网关失败：" + createResult.getMessage());
                            resourceEventPublisher.send(result);
                            return;
                        }

                        NatGatewayModel gatewayModel = JSONObject
                            .parseObject(JSONObject.toJSONString(createResult.getData()), NatGatewayModel.class);
                        BeanUtils.copyProperties(gatewayModel, finalNatGateway);
                        finalNatGateway.setCreatorId(context.getTarget());
                        finalNatGateway.setGmtCreate(gatewayModel.getGmtCreate());
                        finalNatGateway.setVendorId(vendor.getId());
                        finalNatGateway.setVpcId(vpc.getId());
                        finalNatGateway.setSubnetId(subnet.getId());
                        finalNatGateway.setRegionId(natGatewayModel.getRegionId());
                        natGatewayRepository.save(finalNatGateway);
                        result.setSuccess(true);
                        result.setMessage("创建nat网关[" + natGatewayModel.getName() + "]成功");
                        resourceEventPublisher.send(result);

                        try {
                            Long startTime = System.currentTimeMillis();
                            Long endTime = System.currentTimeMillis();
                            while (endTime - startTime < 5 * 60 * 1000) {
                                // 创建时间不确定，增加休眠减少轮询次数
                                Thread.sleep(5000);
                                BocloudResult detailResult = natGatewayDriver.detail(finalNatGateway.getUuid(),
                                    vendor.getUuid(), finalNatGateway.getRegionId());
                                if (detailResult.isSuccess()) {
                                    gatewayModel = (NatGatewayModel)detailResult.getData();
                                    if (!"pending".equals(gatewayModel.getStatus())) {
                                        detailResult = networkInterfaceDriver.detail(vendor.getUuid(),
                                            finalNatGateway.getRegionId(), gatewayModel.getNetworkInterfaceUuid());
                                        if (detailResult.isSuccess()) {
                                            NetworkInterface networkInterface = new NetworkInterface();
                                            NetworkInterfaceModel networkInterfaceModel =
                                                (NetworkInterfaceModel)detailResult.getData();
                                            BeanUtils.copyProperties(networkInterfaceModel, networkInterface);
                                            networkInterface.setCreatorId(context.getTarget());
                                            networkInterface.setVendorId(vendor.getId());
                                            networkInterface.setVpcId(vpc.getId());
                                            networkInterface.setSubnetId(subnet.getId());
                                            networkInterface.setSubnetName(subnet.getName());
                                            networkInterface.setRegionId(finalNatGateway.getRegionId());
                                            networkInterfaceRepository.save(networkInterface);

                                            BocloudResult eipResult =
                                                elasticIpDriver.detail(elasticIp.getElasticIpUuid(), vendor.getUuid(),
                                                    finalNatGateway.getRegionId());
                                            if (eipResult.isSuccess()) {
                                                ElasticIpModel elasticIpModel = (ElasticIpModel)eipResult.getData();
                                                BeanUtils.copyProperties(elasticIpModel, elasticIp);
                                                elasticIp
                                                    .setTagsJson(JSONObject.toJSONString(elasticIpModel.getTags()));
                                                elasticIp.setMenderId(context.getTarget());
                                                elasticIp.setVendorId(vendor.getId());
                                                elasticIp.setGmtModify(new Date());
                                                elasticIp.setRegionId(finalNatGateway.getRegionId());
                                                elasticIpRepository.update(elasticIp);
                                            }

                                            finalNatGateway.setStatus(gatewayModel.getStatus());
                                            finalNatGateway.setNetworkInterfaceId(networkInterface.getId());
                                            finalNatGateway
                                                .setNetworkInterfaceUuid(networkInterface.getNetworkInterfaceUuid());
                                            finalNatGateway
                                                .setPrivateIpAddress(networkInterface.getPrimaryPrivateIPAddress());
                                            natGatewayRepository.update(finalNatGateway);
                                        }
                                        break;
                                    }
                                }
                                endTime = System.currentTimeMillis();
                            }
                        } catch (Exception e) {
                            logger.error("detail NatGateway get status error：", e);
                        }

                        return;
                    });
                    return new BocloudResult<NatGateway>(true, "任务已经下发，正在执行...");
                default:
                    return new BocloudResult<NatGateway>(false, "暂不支持");
            }
        } catch (Exception e) {
            logger.error("create nat gateway failure:" + e.getMessage());
            return new BocloudResult<NatGateway>(false, "创建失败:" + e.getMessage());
        }
    }

    @Override
    public BocloudResult remove(Long id, Boolean force, RequestContext context) {
        try {
            NatGateway dbGateway = natGatewayRepository.query(id);
            if (null == dbGateway) {
                return new BocloudResult<>(false, "该nat网关不存在");
            }
            CloudVendor vendor = cloudVendorRepository.query(dbGateway.getVendorId());
            if (null == vendor) {
                return new BocloudResult<>(false, "云平台不存在");
            }
            CloudProvider provider = CloudProvider.valueOf(vendor.getType());
            switch (provider) {
                case ALIYUN:
                    BocloudResult bocloudResult =
                        natGatewayDriver.remove(vendor.getUuid(), dbGateway.getRegionId(), dbGateway.getUuid(), force);
                    if (bocloudResult.isFailed()) {
                        return bocloudResult;
                    }
                    natGatewayRepository.delete(dbGateway.getId(), context.getTarget());
                    // 删除网卡
                    networkInterfaceRepository.removeByNatUuid(dbGateway.getUuid(), dbGateway.getVendorId(),
                        context.getTarget());
                    // 释放弹性ip
                    elasticIpRepository.removeByInstance(dbGateway.getUuid(), InstanceType.Nat.name(),
                        context.getTarget(), dbGateway.getRegionId(), vendor.getId());
                    // 删除相关规则
                    natGatewayDnatRuleRepository.removeByNatGatewayId(dbGateway.getId(), context.getTarget());
                    natGatewaySnatRuleRepository.removeByNatGatewayId(dbGateway.getId(), context.getTarget());
                    return new BocloudResult<>(true, "NAT网关删除成功");
                default:
                    return new BocloudResult<>(false, "暂不支持");
            }
        } catch (Exception e) {
            logger.error("remove nat gateway failure:" + e.getMessage());
            return new BocloudResult<>(false, "删除失败", null, null);
        }
    }

    @Override
    public BocloudResult remove(Long id, RequestContext context) {
        try {
            NatGateway dbGateway = natGatewayRepository.query(id);
            if (null == dbGateway) {
                return new BocloudResult<>(false, "该nat网关不存在");
            }
            CloudVendor vendor = cloudVendorRepository.query(dbGateway.getVendorId());
            if (null == vendor) {
                return new BocloudResult<>(false, "云平台不存在");
            }
            CloudProvider provider = CloudProvider.valueOf(vendor.getType());
            switch (provider) {
                case HUAWEI:
                    List<NatGatewayDnatRule> natGatewayDnatRules = dnatRuleRepository.listByNatGatewayId(id);
                    List<NatGatewaySnatRule> natGatewaySnatRules = snatRuleRepository.listByNatGatewayId(id);
                    if (natGatewayDnatRules.size() != 0 || natGatewaySnatRules.size() != 0) {
                        return new BocloudResult<>(false, "该nat网关下存在规则，请先删除规则再删除nat网关！");
                    }
                    taskExecutor.submit(() -> {
                        OperateResult result = new OperateResult(true, "", "huawei.removeNatGateway", null,
                            OperateResult.OperateCategory.ResourceEvent, context);
                        try (BocloudACLock lock = lockFactory.getACLock("huawei_removeNatGateway" + id)) {
                            if (!lock.acquire(10, TimeUnit.SECONDS)) {
                                result.setSuccess(false);
                                result.setMessage("删除nat网关失败，当前存在其他互斥任务正在执行，请稍后再试");
                                resourceEventPublisher.send(result);
                                return;
                            }
                            BocloudResult removeResult =
                                natGatewayDriver.remove(vendor.getUuid(), dbGateway.getUuid(), dbGateway.getRegionId());
                            if (removeResult.isFailed()) {
                                result.setSuccess(false);
                                result.setMessage("删除nat网关失败：" + removeResult.getMessage());
                                resourceEventPublisher.send(result);
                                return;
                            }

                            natGatewayRepository.delete(id, context.getTarget());

                            result.setSuccess(true);
                            result.setMessage("删除nat网关[" + dbGateway.getName() + "]成功");
                            resourceEventPublisher.send(result);
                            return;
                        } catch (Exception e) {
                            logger.error("删除nat网关失败：", e);
                            result.setSuccess(false);
                            result.setMessage("删除nat网关失败：" + e.getMessage());
                            resourceEventPublisher.send(result);
                            return;
                        }
                    });
                    return new BocloudResult<>(true, "任务已经下发，正在执行...");
                case AWS:
                    taskExecutor.submit(() -> {
                        OperateResult result = new OperateResult(true, "", "aws.removeNatGateway", null,
                            OperateResult.OperateCategory.ResourceEvent, context);
                        try (BocloudACLock lock = lockFactory.getACLock("aws_removeNatGateway" + id)) {
                            if (!lock.acquire(10, TimeUnit.SECONDS)) {
                                result.setSuccess(false);
                                result.setMessage("删除nat网关失败，当前存在其他互斥任务正在执行，请稍后再试");
                                resourceEventPublisher.send(result);
                                return;
                            }
                            BocloudResult removeResult =
                                natGatewayDriver.remove(vendor.getUuid(), dbGateway.getUuid(), dbGateway.getRegionId());
                            if (removeResult.isFailed()) {
                                result.setSuccess(false);
                                result.setMessage("删除nat网关失败：" + removeResult.getMessage());
                                resourceEventPublisher.send(result);
                                return;
                            }

                            dbGateway.setStatus("deleting");
                            natGatewayRepository.update(dbGateway);

                            Long startTime = System.currentTimeMillis();
                            Long endTime = System.currentTimeMillis();
                            while (endTime - startTime < 5 * 60 * 1000) {
                                // 创建时间不确定，增加休眠减少轮询次数
                                Thread.sleep(5000);
                                BocloudResult detailResult = natGatewayDriver.detail(dbGateway.getUuid(),
                                    vendor.getUuid(), dbGateway.getRegionId());
                                if (detailResult.isSuccess()) {
                                    NatGatewayModel gatewayModel = (NatGatewayModel)detailResult.getData();
                                    if (gatewayModel == null) {
                                        networkInterfaceRepository.delete(dbGateway.getNetworkInterfaceId(),
                                            context.getTarget());
                                        natGatewayRepository.delete(id, context.getTarget());
                                        break;
                                    }
                                }
                                endTime = System.currentTimeMillis();
                            }

                            result.setSuccess(true);
                            result.setMessage("删除nat网关[" + dbGateway.getName() + "]成功");
                            resourceEventPublisher.send(result);

                            ElasticIp elasticIp = elasticIpRepository.queryByPublicIp(dbGateway.getPublicIpAddress());
                            startTime = System.currentTimeMillis();
                            endTime = System.currentTimeMillis();
                            while (endTime - startTime < 5 * 60 * 1000) {
                                // 创建时间不确定，增加休眠减少轮询次数
                                Thread.sleep(5000);
                                BocloudResult detailResult = elasticIpDriver.detail(elasticIp.getElasticIpUuid(),
                                    vendor.getUuid(), dbGateway.getRegionId());
                                if (detailResult.isSuccess()) {
                                    ElasticIpModel elasticIpModel = (ElasticIpModel)detailResult.getData();
                                    if (!elasticIp.getAssociationId().equals(elasticIpModel.getAssociationId())) {
                                        BeanUtils.copyProperties(elasticIpModel, elasticIp);
                                        elasticIp.setTagsJson(JSONObject.toJSONString(elasticIpModel.getTags()));
                                        elasticIp.setMenderId(context.getTarget());
                                        elasticIp.setVendorId(vendor.getId());
                                        elasticIp.setGmtModify(new Date());
                                        elasticIp.setRegionId(dbGateway.getRegionId());
                                        elasticIpRepository.update(elasticIp);
                                        break;
                                    }
                                }
                                endTime = System.currentTimeMillis();
                            }
                            return;
                        } catch (Exception e) {
                            logger.error("删除nat网关失败：", e);
                            result.setSuccess(false);
                            result.setMessage("删除nat网关失败：" + e.getMessage());
                            resourceEventPublisher.send(result);
                            return;
                        }
                    });
                    return new BocloudResult<>(true, "任务已经下发，正在执行...");
                default:
                    return new BocloudResult<>(false, "暂不支持");
            }
        } catch (Exception e) {
            logger.error("remove nat gateway failure:" + e.getMessage());
            return new BocloudResult<>(false, "删除失败", null, null);
        }
    }

    @Override
    public BocloudResult<NatGateway> modify(NatGateway natGateway, RequestContext context) {
        try {
            CloudVendor vendor = cloudVendorRepository.query(natGateway.getVendorId());
            if (null == vendor) {
                return new BocloudResult<NatGateway>(false, "云平台不存在");
            }
            NatGateway dbGateway = natGatewayRepository.query(natGateway.getId());
            if (null == dbGateway) {
                return new BocloudResult<NatGateway>(false, "该nat网关不存在");
            }
            if (!dbGateway.getName().equals(natGateway.getName())
                && null != natGatewayRepository.exists(natGateway.getName(), natGateway.getRegionId())) {
                return new BocloudResult<NatGateway>(false, "nat网关名称已存在");
            }
            CloudProvider provider = CloudProvider.valueOf(vendor.getType());
            NatGatewayModel natGatewayModel = new NatGatewayModel();
            switch (provider) {
                case ALIYUN:
                    BeanUtils.copyProperties(natGateway, natGatewayModel);
                    natGatewayModel.setUuid(dbGateway.getUuid());
                    BocloudResult bocloudResult =
                        natGatewayDriver.update(natGatewayModel, vendor.getUuid(), dbGateway.getRegionId());
                    if (bocloudResult.isFailed()) {
                        return bocloudResult;
                    }
                    NatGatewayModel model =
                        JSONObject.parseObject(JSONObject.toJSONString(bocloudResult.getData()), NatGatewayModel.class);
                    BeanUtils.copyProperties(model, dbGateway);
                    natGateway.setMenderId(context.getTarget());
                    natGateway.setGmtModify(new Date());
                    natGateway.setVendorId(vendor.getId());
                    natGateway.setVpcId(dbGateway.getVpcId());
                    natGateway.setSubnetId(dbGateway.getSubnetId());
                    natGatewayRepository.update(natGateway);
                    return new BocloudResult<NatGateway>(true, "NAT网关修改成功");
                case HUAWEI:

                    BeanUtils.copyProperties(natGateway, natGatewayModel);
                    natGatewayModel.setUuid(dbGateway.getUuid());
                    taskExecutor.submit(() -> {
                        OperateResult result = new OperateResult(true, "", "huawei.modifyNatGateway", null,
                            OperateResult.OperateCategory.ResourceEvent, context);
                        try (BocloudACLock lock =
                            lockFactory.getACLock("huawei_modifyNatGateway" + natGateway.getId())) {
                            if (!lock.acquire(10, TimeUnit.SECONDS)) {
                                result.setSuccess(false);
                                result.setMessage("修改nat网关失败，当前存在其他互斥任务正在执行，请稍后再试");
                                resourceEventPublisher.send(result);
                                return;
                            }
                            BocloudResult modifyResult =
                                natGatewayDriver.update(natGatewayModel, vendor.getUuid(), dbGateway.getRegionId());
                            if (modifyResult.isFailed()) {
                                result.setSuccess(false);
                                result.setMessage("修改nat网关失败：" + modifyResult.getMessage());
                                resourceEventPublisher.send(result);
                                return;
                            }

                            NatGatewayModel gatewayModel = JSONObject
                                .parseObject(JSONObject.toJSONString(modifyResult.getData()), NatGatewayModel.class);
                            BeanUtils.copyProperties(gatewayModel, dbGateway);
                            dbGateway.setMenderId(context.getTarget());
                            dbGateway.setGmtModify(new Date());
                            dbGateway.setVendorId(vendor.getId());
                            natGatewayRepository.update(dbGateway);

                            result.setSuccess(true);
                            result.setMessage("修改nat网关[" + natGatewayModel.getName() + "]成功");
                            resourceEventPublisher.send(result);
                            return;
                        } catch (Exception e) {
                            logger.error("修改nat网关失败：", e);
                            result.setSuccess(false);
                            result.setMessage("修改nat网关失败：" + e.getMessage());
                            resourceEventPublisher.send(result);
                            return;
                        }
                    });

                    return new BocloudResult<NatGateway>(true, "任务已经下发，正在执行...");
                case AWS:
                    BeanUtils.copyProperties(natGateway, natGatewayModel);
                    natGatewayModel.setUuid(dbGateway.getUuid());
                    taskExecutor.submit(() -> {
                        OperateResult result = new OperateResult(true, "", "aws.modifyNatGateway", null,
                            OperateResult.OperateCategory.ResourceEvent, context);
                        try (BocloudACLock lock = lockFactory.getACLock("aws_modifyNatGateway" + natGateway.getId())) {
                            if (!lock.acquire(10, TimeUnit.SECONDS)) {
                                result.setSuccess(false);
                                result.setMessage("修改nat网关失败，当前存在其他互斥任务正在执行，请稍后再试");
                                resourceEventPublisher.send(result);
                                return;
                            }
                            BocloudResult modifyResult =
                                natGatewayDriver.update(natGatewayModel, vendor.getUuid(), dbGateway.getRegionId());
                            if (modifyResult.isFailed()) {
                                result.setSuccess(false);
                                result.setMessage("修改nat网关失败：" + modifyResult.getMessage());
                                resourceEventPublisher.send(result);
                                return;
                            }

                            NatGatewayModel gatewayModel = JSONObject
                                .parseObject(JSONObject.toJSONString(modifyResult.getData()), NatGatewayModel.class);
                            BeanUtils.copyProperties(gatewayModel, dbGateway);
                            dbGateway.setVpcId(natGateway.getVpcId());
                            dbGateway.setSubnetId(natGateway.getSubnetId());
                            dbGateway.setNetworkInterfaceId(natGateway.getNetworkInterfaceId());
                            dbGateway.setMenderId(context.getTarget());
                            dbGateway.setGmtModify(new Date());
                            dbGateway.setVendorId(vendor.getId());
                            dbGateway.setRegionId(natGateway.getRegionId());
                            natGatewayRepository.update(dbGateway);

                            result.setSuccess(true);
                            result.setMessage("修改nat网关[" + natGatewayModel.getName() + "]成功");
                            resourceEventPublisher.send(result);
                            return;
                        } catch (Exception e) {
                            logger.error("修改nat网关失败：", e);
                            result.setSuccess(false);
                            result.setMessage("修改nat网关失败：" + e.getMessage());
                            resourceEventPublisher.send(result);
                            return;
                        }
                    });

                    return new BocloudResult<NatGateway>(true, "任务已经下发，正在执行...");
                default:
                    return new BocloudResult<NatGateway>(false, "暂不支持");
            }

        } catch (Exception e) {
            logger.error("modify nat gateway failure:" + e.getMessage());
            return new BocloudResult<NatGateway>(false, "修改失败", null, null);
        }
    }

    @Override
    public BocloudResult<NatGateway> detail(Long id) {
        try {
            NatGateway natGateway = natGatewayRepository.query(id);
            return new BocloudResult<NatGateway>(true, natGateway, "查询成功");
        } catch (Exception e) {
            logger.error("query natGateway failure:", e);
            return new BocloudResult<NatGateway>(false, "查询失败", null, null);
        }
    }

    @Override
    public BocloudResult<List<NatGateway>> listAvailableGateway(Long vendorId, String regionId) {
        try {
            return new BocloudResult<>(true, natGatewayRepository.listAvailableGateway(vendorId, regionId), "查询成功");
        } catch (Exception e) {
            logger.error("Get error message:{}", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    @Override
    public BocloudResult<List<NatGateway>> listAvailableGateway(Long vendorId, Long routeTableId) {
        try {
            RouteTable routeTable = routeTableRepository.query(routeTableId);
            if (null == routeTable) {
                logger.error("Get error message:{}", "路由不存在");
                return new BocloudResult<>(false, "查询失败");
            }
            return new BocloudResult<>(true, natGatewayRepository.listAvailableForRoute(vendorId, routeTable.getUuid(),
                routeTable.getRegionId(), routeTable.getVpcUuid()), "查询成功");
        } catch (Exception e) {
            logger.error("Get error message:{}", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    @Override
    public BocloudResult<List<String>> listBindElasticIp(Long natGatewayId) {
        try {
            List<String> ips = new ArrayList<>();
            ips.addAll(dnatRuleRepository.listIpsByNatGatewayId(natGatewayId));
            ips.addAll(snatRuleRepository.listIpsByNatGatewayId(natGatewayId));
            return new BocloudResult<>(true, ips, "查询成功");
        } catch (Exception e) {
            logger.error("Get error message:{}", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    @Override
    public BocloudResult<List<Map<String, Object>>> listAvailablePrivateIp(Long natGatewayId) {

        try {
            NatGateway gateway = natGatewayRepository.query(natGatewayId);
            if (null == gateway) {
                return new BocloudResult<>(false, "该nat网关不存在");
            }
            List<NetworkInterface> list = networkInterfaceRepository.listForNatGatewayRule(gateway.getVendorId(),
                gateway.getRegionId(), gateway.getVpcId());
            List<String> bindIps = dnatRuleRepository.listBindPrivateIps(natGatewayId);
            List<Map<String, Object>> dataList = new ArrayList<>();
            for (NetworkInterface net : list) {
                String typeName = NetworkInterface.InterfaceType.Primary.name().endsWith(net.getInterfaceType()) ? "主网卡"
                    : NetworkInterface.InterfaceType.Secondary.name().endsWith(net.getInterfaceType()) ? "辅助网卡" : "";
                if (!bindIps.contains(net.getPrimaryPrivateIPAddress())) {
                    Map<String, Object> map = new HashMap<>();
                    map.put("id", net.getId());
                    map.put("name", net.getName());
                    map.put("privateIp", net.getPrimaryPrivateIPAddress());
                    map.put("interfaceType", net.getInterfaceType());
                    map.put("interfaceTypeName", typeName);
                    dataList.add(map);
                }
                if (StringUtils.isEmpty(net.getPrivateIPAddress())) {
                    continue;
                }
                List<String> ips = JSONArray.parseArray(net.getPrivateIPAddress(), String.class);
                for (String ip : ips) {
                    if (!bindIps.contains(ip)) {
                        Map<String, Object> map2 = new HashMap<>();
                        map2.put("id", net.getId());
                        map2.put("name", net.getName());
                        map2.put("privateIp", ip);
                        map2.put("interfaceType", net.getInterfaceType());
                        map2.put("interfaceTypeName", typeName);
                        dataList.add(map2);
                    }
                }
            }

            return new BocloudResult<>(true, dataList, "查询成功");
        } catch (Exception e) {
            logger.error("Get error message:{}", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    @Override
    public BocloudResult<List<NatGateway>> list(Long vendorId, String regionId, Long vpcId) {
        try {
            return new BocloudResult<>(true, natGatewayRepository.list(vendorId, regionId, vpcId), "查询成功");
        } catch (Exception e) {
            logger.error("Get error message:{}", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

}
