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

import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.azure.account.StorageAccountDriver;
import com.bocloud.cmp.model.NotifyMessage;
import com.bocloud.cmp.model.azure.account.StorageAccountFirewallModel;
import com.bocloud.cmp.model.azure.account.StorageAccountModel;
import com.bocloud.cmp.params.azure.StorageAccountCheckNameParams;
import com.bocloud.cmp.params.azure.UserAssignParams;
import com.bocloud.common.model.*;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.ListTool;
import com.bocloud.common.utils.MapTools;
import com.bocloud.ims.common.enums.azure.AzureSubnetRelationType;
import com.bocloud.ims.common.enums.azure.AzureTaskStatus;
import com.bocloud.ims.entity.common.Project;
import com.bocloud.ims.entity.resource.CloudVendor;
import com.bocloud.ims.entity.resource.ResourceGroup;
import com.bocloud.ims.entity.resource.Subnet;
import com.bocloud.ims.entity.resource.Vpc;
import com.bocloud.ims.entity.resource.azure.account.StorageAccount;
import com.bocloud.ims.entity.resource.azure.account.StorageAccountFirewall;
import com.bocloud.ims.entity.resource.azure.blob.Container;
import com.bocloud.ims.entity.resource.azure.network.ResourceSubnetRelation;
import com.bocloud.ims.interfaces.resource.azure.account.StorageAccountService;
import com.bocloud.ims.repository.resource.CloudVendorRepository;
import com.bocloud.ims.repository.resource.ResourceGroupRepository;
import com.bocloud.ims.repository.resource.SubnetRepository;
import com.bocloud.ims.repository.resource.VpcRepository;
import com.bocloud.ims.repository.resource.azure.account.StorageAccountFirewallRepository;
import com.bocloud.ims.repository.resource.azure.account.StorageAccountRepository;
import com.bocloud.ims.repository.resource.azure.blob.BlobRepository;
import com.bocloud.ims.repository.resource.azure.blob.ContainerRepository;
import com.bocloud.ims.repository.resource.azure.network.ResourceSubnetRelationRepository;
import com.bocloud.ims.service.internal.SmsProjectService;
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.BeanUtils;
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.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @Company: 博云 www.bocloud.com
 * @ClassName: StorageAccountServiceImpl
 * @Description:
 * @author: zhenpingLi/李振平
 * @date: 2020/7/24 14:18
 */
@Service("storageAccountService")
public class StorageAccountServiceImpl implements StorageAccountService {

    private static OperateResult.OperateCategory operateCategory = OperateResult.OperateCategory.ResourceEvent;
    private static Logger logger = LoggerFactory.getLogger(StorageAccountServiceImpl.class);

    @Autowired
    private ResourceGroupRepository resourceGroupRepository;
    @Autowired
    private StorageAccountRepository storageAccountRepository;
    @Autowired
    private CloudVendorRepository vendorRepository;
    @Autowired
    private ContainerRepository containerRepository;
    @Autowired
    private BlobRepository blobRepository;
    @Autowired
    private SubnetRepository subnetRepository;
    @Autowired
    private StorageAccountFirewallRepository storageAccountFirewallRepository;
    @Autowired
    private VpcRepository vpcRepository;
    @Autowired
    private ResourceSubnetRelationRepository resourceSubnetRelationRepository;
    @Autowired
    private StorageAccountDriver storageAccountDriver;
    @Autowired
    private AmqpTemplate amqpTemplate;
    @Autowired
    private SmsProjectService smsProjectService;
    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;
    @Autowired
    private ResourceEventPublisher resourceEventPublisher;
    @Autowired
    private LockFactory lockFactory;

    @Override
    public BocloudResult<Void> create(StorageAccount entityParams, RequestContext context) {
        try {
            CloudVendor vendor = vendorRepository.query(entityParams.getVendorId());
            Assert.notNull(vendor, "平台不存在");
            if (null != storageAccountRepository.getByName(entityParams.getVendorId(), entityParams.getResourceGroupId(), entityParams.getName())) {
                return new BocloudResult<>(false, "名称已存在");
            }
            ResourceGroup resourceGroup = resourceGroupRepository.query(entityParams.getResourceGroupId());
            Assert.notNull(resourceGroup, "资源组不存在");

            StorageAccountModel model = new StorageAccountModel();
            BeanUtils.copyProperties(entityParams, model);
            model.setResourceGroupName(resourceGroup.getName());

            //增加状态
            entityParams.setCreatorId(context.getTarget());
            entityParams.setGmtCreate(new Date());
            entityParams.setTenantId(context.getTenant());
            entityParams.setProjectId(context.getProject());
            if (context.getCatalog() == RequestContext.Catalog.User) {
                entityParams.setUserId(context.getTarget());
            }
            entityParams.setStatus(AzureTaskStatus.BUILDING.name());
            storageAccountRepository.save(entityParams);

            taskExecutor.execute(() -> {
                String operate = vendor.getType().toLowerCase() + ".storageaccount";
                String message = "创建存储对象失败";
                BocloudResult result = storageAccountDriver.create(vendor.getUuid(), entityParams.getRegionId(), model);
                try {
                    if (result.isSuccess()) {
                        message = "创建存储对象成功";
                        StorageAccountModel newModel = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), StorageAccountModel.class);
                        BeanUtils.copyProperties(newModel, entityParams);
                        entityParams.setStatus(AzureTaskStatus.AVAILABLE.name());
                        storageAccountRepository.update(entityParams);
                        logger.info("{}：存储账户创建成功！", entityParams.getName());
                    } else {
                        logger.info("{}：存储账户创建失败！", entityParams.getName());
                        logger.error("创建存储对象失败：" + result.getMessage());
                        message = result.getMessage();
                        storageAccountRepository.remove(entityParams.getId(), context.getTarget());
                    }
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                } catch (Exception e) {
                    logger.info("{}：存储账户创建失败！", entityParams.getName());
                    logger.error("create storageAccount fail:", e);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate, MapTools.simpleMap(
                            "vendorId", vendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult<>(true, "任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("create storageAccount error!", e);
            return new BocloudResult<>(false, "创建失败:" + e.getMessage());
        }
    }

    @Override
    public BocloudResult<Void> remove(Long id, RequestContext context) {
        String path = StorageAccount.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            StorageAccount entity = storageAccountRepository.query(id);
            Assert.notNull(entity, "资源不存在");
            CloudVendor vendor = vendorRepository.query(entity.getVendorId());
            Assert.notNull(vendor, "平台不存在");
            taskExecutor.execute(() -> {
                String operate = vendor.getType().toLowerCase() + ".storageaccount";
                String message = "删除存储对象失败";
                BocloudResult result = storageAccountDriver.remove(vendor.getUuid(), entity.getRegionId(), entity.getUuid());
                try {
                    if (result.isSuccess()) {
                        message = "删除存储对象成功";
                        storageAccountRepository.remove(id, context.getTarget());
                        List<Container> containers = containerRepository.listByCondition(vendor.getId(), id);
                        for (Container container : containers) {
                            blobRepository.removeByContainerId(container.getId(), context.getTarget());
                        }
                        containerRepository.removeByAccountId(id, context.getTarget());
                    } else {
                        logger.error("删除存储对象失败：" + result.getMessage());
                        message = result.getMessage();
                    }
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                } catch (Exception e) {
                    logger.error("remove storageAccount fail:", e);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult<>(true, "任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("remove storageAccount error!", e);
            return new BocloudResult<>(false, "删除失败:" + e.getMessage());
        }
    }

    @Override
    public BocloudResult<StorageAccount> assign(UserAssignParams params, RequestContext context) {
        // 资源ID
        Long id = params.getId();
        // 租户用户ID
        Long userId = params.getUserId();
        // 租户用户所在项目
        Long projectId = params.getProjectId();
        Long tenantId = params.getTenantId();
        try {
            StorageAccount entity = storageAccountRepository.query(id);
            Assert.notNull(entity, "数据不存在");
            entity.setTenantId(tenantId);
            entity.setProjectId(projectId);
            entity.setUserId(userId);
            storageAccountRepository.update(entity);
            return new BocloudResult<>(true, entity, "操作成功");
        } catch (Exception e) {
            logger.error("assign storageAccount  fail:", e);
            return new BocloudResult<>(false, "操作失败:" + e.getMessage());
        }
    }

    @Override
    public BocloudResult<Void> assignBatch(UserAssignParams params, RequestContext context) {
        Long userId = params.getUserId();
        // 租户用户所在项目
        Long projectId = params.getProjectId();
        Long tenantId = params.getTenantId();
        List<Long> ids = params.getIds();
        for (Long id : ids) {
            UserAssignParams newParams = new UserAssignParams();
            newParams.setId(id);
            newParams.setUserId(userId);
            newParams.setTenantId(tenantId);
            newParams.setProjectId(projectId);
            this.assign(newParams, context);
        }
        return new BocloudResult<>(true, "操作成功");
    }

    @Override
    public BocloudResult checkName(StorageAccountCheckNameParams params, RequestContext context) {
        Long vendorId = params.getVendorId();
        String name = params.getName();
        String regionId = params.getRegionId();
        Long resourceGroupId = params.getResourceGroupId();
        try {
            CloudVendor vendor = vendorRepository.query(vendorId);
            Assert.notNull(vendor, "平台不存在");
            if (null != storageAccountRepository.getByName(vendorId, resourceGroupId, name)) {
                return new BocloudResult(false, "名称已存在");
            }
            return storageAccountDriver.checkName(vendor.getUuid(), regionId, name);
        } catch (Exception e) {
            logger.error("checkName storageAccount error!", e);
            return new BocloudResult(false, "名称校验失败:" + e.getMessage());
        }
    }

    @Override
    public BocloudResult<GridBean<StorageAccount>> list(Pager pager, RequestContext context) {
        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);
        Boolean simple = Optional.ofNullable(pager.getSimple()).orElse(false);
        Integer page = Optional.ofNullable(pager.getPage()).orElse(1);
        Integer rows = Optional.ofNullable(pager.getRows()).orElse(10);

        List<StorageAccount> list;
        int total;
        GridBean<StorageAccount> gridBean;
        try {
            Long tenantId = context.getTenant();
            Long projectId = context.getProject();

            // 为租户下的用户
            if (null != tenantId && 0L != tenantId) {
                List<Project> projects = smsProjectService.projectsByCondition(context.getTarget(),
                        context.getCatalog());
                List<Long> projectIds = new ArrayList<>();
                // 此时查询的是全部用户全部项目的信息
                if (null != projectId && 0L != projectId) {
                    projectIds.add(projectId);
                } else if (!ListTool.isEmpty(projects)) {
                    projects.forEach(project -> projectIds.add(project.getId()));
                } else {
                    projectIds.add(-1L);
                }
                total = this.storageAccountRepository.count(params, null, projectIds, null);
                list = this.storageAccountRepository.list(page, rows, params, sorter, null, projectIds, null);
            } else {
                list = storageAccountRepository.list(page, rows, params, sorter);
                total = storageAccountRepository.count(params);
            }
            gridBean = new GridBean<>(page, rows, total, list);
            return new BocloudResult<>(true, gridBean, "查询成功");
        } catch (Exception e) {
            logger.error("list storageAccount error!", e);
            return new BocloudResult<>(false, "查询失败:" + e.getMessage());
        }
    }

    @Override
    public BocloudResult<StorageAccount> detail(Long id, RequestContext context) {
        try {
            StorageAccount entity = storageAccountRepository.query(id);
            Assert.notNull(entity, "数据不存在");
            List<ResourceSubnetRelation> subnetRelations = resourceSubnetRelationRepository.listByResourceId(entity.getId(), AzureSubnetRelationType.STORAGEACCOUNT.name());
            List<Subnet> subnets = new ArrayList<>();
            for (ResourceSubnetRelation subnetRelation : subnetRelations) {
                Subnet subnet = subnetRepository.query(subnetRelation.getSubnetId());
                if (!ObjectUtils.isEmpty(subnet)) {
                    subnets.add(subnet);
                }
            }
            entity.setSubnets(subnets);
            List<StorageAccountFirewall> firewalls = new ArrayList<>();
            List<StorageAccountFirewall> storageAccountFirewalls = storageAccountFirewallRepository.listBySAId(entity.getId());
            if (!CollectionUtils.isEmpty(storageAccountFirewalls)) {
                firewalls.addAll(storageAccountFirewalls);
            }
            entity.setFirewalls(firewalls);
            return new BocloudResult(true, entity, "查询详情成功");
        } catch (Exception e) {
            logger.error("query storageAccount error!", e);
            return new BocloudResult<>(false, "查询详情失败:" + e.getMessage());
        }
    }

    @Override
    public BocloudResult<Void> modify(StorageAccount modifyParams, RequestContext context) {
        try {
            StorageAccount entity = storageAccountRepository.query(modifyParams.getId());
            Assert.notNull(entity, "资源不存在");
            CloudVendor vendor = vendorRepository.query(entity.getVendorId());
            Assert.notNull(vendor, "平台验证失败");
            StorageAccountModel model = new StorageAccountModel();
            model.setSku(modifyParams.getSku());
            model.setUuid(entity.getUuid());
            //增加状态
            entity.setStatus(AzureTaskStatus.IN_USE.name());
            storageAccountRepository.update(entity);
            taskExecutor.execute(() -> {
                String operate = vendor.getType().toLowerCase() + ".storageaccount";
                String message = "存储对象更新复制级别失败";
                BocloudResult result = storageAccountDriver.modify(vendor.getUuid(), entity.getRegionId(), model);
                try {
                    if (result.isSuccess()) {
                        message = "尊敬的客户，您好！您的存储对象【" + entity.getName() + "】于" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "更新复制级别成功，请登录控制台查看及管理。";
                        StorageAccountModel newModel = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), StorageAccountModel.class);
                        entity.setSku(newModel.getSku());
                        entity.setStatus(AzureTaskStatus.AVAILABLE.name());
                        storageAccountRepository.update(entity);
                    } else {
                        logger.error("存储对象更新复制级别失败：" + result.getMessage());
                        message = "尊敬的客户，您好！您的存储对象【" + entity.getName() + "】于" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "更新复制级别失败，失败信息：" + result.getMessage();
                        entity.setStatus(AzureTaskStatus.AVAILABLE.name());
                        storageAccountRepository.update(entity);
                    }
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                } catch (Exception e) {
                    logger.error("customDomain storageAccount fail:", e);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate, MapTools.simpleMap(
                            "vendorId", vendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult<>(true, "任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("customDomain storageAccount error!", e);
            return new BocloudResult<>(false, "更新复制级别失败:" + e.getMessage());
        }
    }

    @Override
    public BocloudResult<Void> customDomain(StorageAccount modifyParams, RequestContext context) {
        try {
            StorageAccount entity = storageAccountRepository.query(modifyParams.getId());
            Assert.notNull(entity, "资源不存在");
            CloudVendor vendor = vendorRepository.query(entity.getVendorId());
            Assert.notNull(vendor, "平台验证失败");
            StorageAccountModel model = new StorageAccountModel();
            model.setCustomDomain(modifyParams.getCustomDomain());
            model.setUuid(entity.getUuid());
            //增加状态
            entity.setStatus(AzureTaskStatus.IN_USE.name());
            storageAccountRepository.update(entity);
            taskExecutor.execute(() -> {
                String operate = vendor.getType().toLowerCase() + ".storageaccount";
                String message = "存储对象自定义域失败";
                BocloudResult result = storageAccountDriver.customDomain(vendor.getUuid(), entity.getRegionId(), model);
                try {
                    if (result.isSuccess()) {
                        message = "尊敬的客户，您好！您的存储对象【" + entity.getName() + "】于" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "自定义域成功，请登录控制台查看及管理。";
                        StorageAccountModel newModel = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), StorageAccountModel.class);
                        entity.setCustomDomain(newModel.getCustomDomain());
                        entity.setStatus(AzureTaskStatus.AVAILABLE.name());
                        storageAccountRepository.update(entity);
                    } else {
                        logger.error("存储对象自定义域失败：" + result.getMessage());
                        message = "尊敬的客户，您好！您的存储对象【" + entity.getName() + "】于" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "自定义域失败，失败信息：" + result.getMessage();
                        entity.setStatus(AzureTaskStatus.AVAILABLE.name());
                        storageAccountRepository.update(entity);
                    }
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                } catch (Exception e) {
                    logger.error("customDomain storageAccount fail:", e);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate, MapTools.simpleMap(
                            "vendorId", vendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult<>(true, "任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("customDomain storageAccount error!", e);
            return new BocloudResult<>(false, "创建失败:" + e.getMessage());
        }

    }

    @Override
    public BocloudResult<Void> minimumTlsVersion(StorageAccount modifyParams, RequestContext context) {
        try {
            StorageAccount entity = storageAccountRepository.query(modifyParams.getId());
            Assert.notNull(entity, "资源不存在");
            CloudVendor vendor = vendorRepository.query(entity.getVendorId());
            Assert.notNull(vendor, "平台验证失败");
            ResourceGroup resourceGroup = resourceGroupRepository.query(entity.getResourceGroupId());
            Assert.notNull(resourceGroup, "资源组验证失败");

            StorageAccountModel model = new StorageAccountModel();
            model.setName(entity.getName());
            model.setResourceGroupName(resourceGroup.getName());
            model.setMinimumTlsVersion(modifyParams.getMinimumTlsVersion());
            //增加状态
            entity.setStatus(AzureTaskStatus.IN_USE.name());
            storageAccountRepository.update(entity);
            taskExecutor.execute(() -> {
                String operate = vendor.getType().toLowerCase() + ".storageaccount";
                String message = "存储对象TLS版本设置失败";
                BocloudResult result = storageAccountDriver.minimumTlsVersion(vendor.getUuid(), entity.getRegionId(), model);
                try {
                    if (result.isSuccess()) {
                        message = "尊敬的客户，您好！您的存储对象【" + entity.getName() + "】于" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "TLS版本设置成功，请登录控制台查看及管理。";
                        entity.setMinimumTlsVersion(modifyParams.getMinimumTlsVersion());
                        entity.setStatus(AzureTaskStatus.AVAILABLE.name());
                        storageAccountRepository.update(entity);
                    } else {
                        logger.error("存储对象TLS版本设置失败：" + result.getMessage());
                        message = "尊敬的客户，您好！您的存储对象【" + entity.getName() + "】于" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "TLS版本设置失败，失败信息：" + result.getMessage();
                        entity.setStatus(AzureTaskStatus.AVAILABLE.name());
                        storageAccountRepository.update(entity);
                    }
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                } catch (Exception e) {
                    logger.error("minimumTlsVersion storageAccount fail:", e);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate, MapTools.simpleMap(
                            "vendorId", vendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult<>(true, "任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("minimumTlsVersion storageAccount error!", e);
            return new BocloudResult<>(false, "更新失败:" + e.getMessage());
        }

    }

    @Override
    public BocloudResult<Void> regenerateKey(StorageAccount modifyParams, RequestContext context) {
        try {
            StorageAccount entity = storageAccountRepository.query(modifyParams.getId());
            Assert.notNull(entity, "资源不存在");
            CloudVendor vendor = vendorRepository.query(entity.getVendorId());
            Assert.notNull(vendor, "平台验证失败");

            StorageAccountModel model = new StorageAccountModel();
            model.setUuid(entity.getUuid());
            model.setRegenerateKey(modifyParams.getRegenerateKey());
            //增加状态
            entity.setStatus(AzureTaskStatus.IN_USE.name());
            storageAccountRepository.update(entity);
            taskExecutor.execute(() -> {
                String operate = vendor.getType().toLowerCase() + ".storageaccount";
                String message = "存储对象再生密钥失败";
                BocloudResult result = storageAccountDriver.regenerateKey(vendor.getUuid(), entity.getRegionId(), model);
                try {
                    if (result.isSuccess()) {
                        message = "尊敬的客户，您好！您的存储对象【" + entity.getName() + "】于" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "再生密钥成功，请登录控制台查看及管理。";
                        StorageAccountModel newModel = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), StorageAccountModel.class);
                        entity.setPrimaryKey(newModel.getPrimaryKey());
                        entity.setSecondaryKey(newModel.getSecondaryKey());
                        entity.setStatus(AzureTaskStatus.AVAILABLE.name());
                        storageAccountRepository.update(entity);
                    } else {
                        logger.error("存储对象再生密钥失败：" + result.getMessage());
                        message = "尊敬的客户，您好！您的存储对象【" + entity.getName() + "】于" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "再生密钥失败，失败信息：" + result.getMessage();
                        entity.setStatus(AzureTaskStatus.AVAILABLE.name());
                        storageAccountRepository.update(entity);
                    }
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                    //站内信推送
                    NotifyMessage notifyMessage = new NotifyMessage(context, "StorageAccount:", message, null,
                            true, false);
                    amqpTemplate.convertAndSend("event.notice.queue", notifyMessage);
                } catch (Exception e) {
                    logger.error("regenerateKey storageAccount fail:", e);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate, MapTools.simpleMap(
                            "vendorId", vendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult<>(true, "任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("regenerateKey storageAccount error!", e);
            return new BocloudResult<>(false, "更新失败:" + e.getMessage());
        }

    }

    @Override
    public BocloudResult<Void> withAccessFromNetworkSubnet(StorageAccount modifyParams, RequestContext context) {
        try {
            StorageAccount entity = storageAccountRepository.query(modifyParams.getId());
            Assert.notNull(entity, "资源不存在");
            CloudVendor vendor = vendorRepository.query(entity.getVendorId());
            Assert.notNull(vendor, "平台验证失败");
            Subnet subnet = subnetRepository.query(modifyParams.getSubnetId());
            Assert.notNull(subnet, "子网不存在");
            Vpc vpc = vpcRepository.query(subnet.getNetworkId());
            Assert.notNull(vpc, "VPC不存在");
            StorageAccountModel model = new StorageAccountModel();
            model.setUuid(entity.getUuid());
            model.setSubnetUuid(subnet.getSubnetUuid());
            model.setVpcUuid(vpc.getVpcId());
            model.setSubnetName(subnet.getName());
            //增加状态
            entity.setStatus(AzureTaskStatus.IN_USE.name());
            storageAccountRepository.update(entity);
            taskExecutor.execute(() -> {
                String operate = vendor.getType().toLowerCase() + ".storageaccount";
                String message = "存储对象添加虚拟网络失败";
                BocloudResult result = storageAccountDriver.withAccessFromNetworkSubnet(vendor.getUuid(), entity.getRegionId(), model);
                try {
                    if (result.isSuccess()) {
                        message = "尊敬的客户，您好！您的存储对象【" + entity.getName() + "】于" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "添加虚拟网络成功，请登录控制台查看及管理。";
                        ResourceSubnetRelation relation = new ResourceSubnetRelation();
                        relation.setResourceId(entity.getId());
                        relation.setVpcId(subnet.getVpcId());
                        relation.setSubnetId(subnet.getId());
                        relation.setResourceType(AzureSubnetRelationType.STORAGEACCOUNT.name());
                        resourceSubnetRelationRepository.save(relation);
                        entity.setIsAccessAllNetworks(false);
                        entity.setStatus(AzureTaskStatus.AVAILABLE.name());
                        storageAccountRepository.update(entity);
                    } else {
                        logger.error("存储对象添加虚拟网络失败：" + result.getMessage());
                        message = "尊敬的客户，您好！您的存储对象【" + entity.getName() + "】于" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "添加虚拟网络失败，失败信息：" + result.getMessage();
                        entity.setStatus(AzureTaskStatus.AVAILABLE.name());
                        storageAccountRepository.update(entity);
                    }
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                    //站内信推送
                    NotifyMessage notifyMessage = new NotifyMessage(context, "StorageAccount:", message, null,
                            true, false);
                    amqpTemplate.convertAndSend("event.notice.queue", notifyMessage);
                } catch (Exception e) {
                    logger.error("withAccessFromNetworkSubnet storageAccount fail:", e);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate, MapTools.simpleMap(
                            "vendorId", vendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult<>(true, "任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("withAccessFromNetworkSubnet storageAccount error!", e);
            return new BocloudResult<>(false, "更新失败:" + e.getMessage());
        }

    }

    @Override
    public BocloudResult<Void> withoutNetworkSubnetAccess(StorageAccount modifyParams, RequestContext context) {
        try {
            StorageAccount entity = storageAccountRepository.query(modifyParams.getId());
            Assert.notNull(entity, "资源不存在");
            CloudVendor vendor = vendorRepository.query(entity.getVendorId());
            Assert.notNull(vendor, "平台验证失败");
            Subnet subnet = subnetRepository.query(modifyParams.getSubnetId());
            Assert.notNull(subnet, "子网不存在");

            StorageAccountModel model = new StorageAccountModel();
            model.setUuid(entity.getUuid());
            model.setSubnetUuid(subnet.getSubnetUuid());
            //增加状态
            entity.setStatus(AzureTaskStatus.IN_USE.name());
            storageAccountRepository.update(entity);
            taskExecutor.execute(() -> {
                String operate = vendor.getType().toLowerCase() + ".storageaccount";
                String message = "存储对象删除虚拟网络失败";
                BocloudResult result = storageAccountDriver.withoutNetworkSubnetAccess(vendor.getUuid(), entity.getRegionId(), model);
                try {
                    if (result.isSuccess()) {
                        message = "尊敬的客户，您好！您的存储对象【" + entity.getName() + "】于" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "删除虚拟网络成功，请登录控制台查看及管理。";
                        resourceSubnetRelationRepository.removeBySubnetIdAndResourceId(subnet.getId(), entity.getId(), AzureSubnetRelationType.STORAGEACCOUNT.name());
                        entity.setStatus(AzureTaskStatus.AVAILABLE.name());
                        storageAccountRepository.update(entity);
                    } else {
                        logger.error("存储对象删除虚拟网络失败：" + result.getMessage());
                        message = "尊敬的客户，您好！您的存储对象【" + entity.getName() + "】于" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "删除虚拟网络失败，失败信息：" + result.getMessage();
                        entity.setIsAccessAllNetworks(false);
                        entity.setStatus(AzureTaskStatus.AVAILABLE.name());
                        storageAccountRepository.update(entity);
                    }
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                    //站内信推送
                    NotifyMessage notifyMessage = new NotifyMessage(context, "StorageAccount:", message, null,
                            true, false);
                    amqpTemplate.convertAndSend("event.notice.queue", notifyMessage);
                } catch (Exception e) {
                    logger.error("withoutNetworkSubnetAccess storageAccount fail:", e);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate, MapTools.simpleMap(
                            "vendorId", vendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult<>(true, "任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("withoutNetworkSubnetAccess storageAccount error!", e);
            return new BocloudResult<>(false, "更新失败:" + e.getMessage());
        }

    }

    @Override
    public BocloudResult<Void> withAccessFromAllNetworks(StorageAccount modifyParams, RequestContext context) {
        try {
            StorageAccount entity = storageAccountRepository.query(modifyParams.getId());
            Assert.notNull(entity, "资源不存在");
            CloudVendor vendor = vendorRepository.query(entity.getVendorId());
            Assert.notNull(vendor, "平台验证失败");

            StorageAccountModel model = new StorageAccountModel();
            model.setUuid(entity.getUuid());
            //增加状态
            entity.setStatus(AzureTaskStatus.IN_USE.name());
            storageAccountRepository.update(entity);
            taskExecutor.execute(() -> {
                this.withoutNetworkSubnets(entity, vendor);
                this.withoutIpAddress(entity, vendor);
                String operate = vendor.getType().toLowerCase() + ".storageaccount";
                String message = "存储对象访问来源所有网络失败";
                BocloudResult result = storageAccountDriver.withAccessFromAllNetworks(vendor.getUuid(), entity.getRegionId(), model);
                try {
                    if (result.isSuccess()) {
                        message = "尊敬的客户，您好！您的存储对象【" + entity.getName() + "】于" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "访问来源所有网络成功，请登录控制台查看及管理。";
                        entity.setIsAccessAllNetworks(true);
                        entity.setStatus(AzureTaskStatus.AVAILABLE.name());
                        storageAccountRepository.update(entity);
                    } else {
                        logger.error("存储对象访问来源所有网络失败：" + result.getMessage());
                        message = "尊敬的客户，您好！您的存储对象【" + entity.getName() + "】于" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "访问来源所有网络失败，失败信息：" + result.getMessage();
                        entity.setStatus(AzureTaskStatus.AVAILABLE.name());
                        storageAccountRepository.update(entity);
                    }
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                    //站内信推送
                    NotifyMessage notifyMessage = new NotifyMessage(context, "StorageAccount:", message, null,
                            true, false);
                    amqpTemplate.convertAndSend("event.notice.queue", notifyMessage);
                } catch (Exception e) {
                    logger.error("withAccessFromAllNetworks storageAccount fail:", e);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate, MapTools.simpleMap(
                            "vendorId", vendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult<>(true, "任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("withAccessFromAllNetworks storageAccount error!", e);
            return new BocloudResult<>(false, "更新失败:" + e.getMessage());
        }

    }

    @Override
    public BocloudResult<Void> withAccessFromIpAddress(StorageAccountFirewall entityParams, RequestContext context) {
        try {
            StorageAccount storageAccount = storageAccountRepository.query(entityParams.getStorageAccountId());
            Assert.notNull(storageAccount, "资源不存在");
            CloudVendor vendor = vendorRepository.query(storageAccount.getVendorId());
            Assert.notNull(vendor, "平台验证失败");

            StorageAccountFirewallModel model = new StorageAccountFirewallModel();
            BeanUtils.copyProperties(entityParams, model);
            model.setStorageAccountUuid(storageAccount.getUuid());

            //增加状态
            storageAccount.setStatus(AzureTaskStatus.IN_USE.name());
            storageAccountRepository.update(storageAccount);
            taskExecutor.execute(() -> {
                String operate = vendor.getType().toLowerCase() + ".storageaccount";
                String message = "存储对象添加IP失败";
                BocloudResult result = storageAccountDriver.withAccessFromIpAddress(vendor.getUuid(), storageAccount.getRegionId(), model);
                try {
                    if (result.isSuccess()) {
                        message = "尊敬的客户，您好！您的存储对象【" + storageAccount.getName() + "】于" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "添加IP成功，请登录控制台查看及管理。";
                        storageAccountFirewallRepository.save(entityParams);
                        storageAccount.setStatus(AzureTaskStatus.AVAILABLE.name());
                        storageAccountRepository.update(storageAccount);
                    } else {
                        logger.error("存储对象添加IP失败：" + result.getMessage());
                        message = "尊敬的客户，您好！您的存储对象【" + storageAccount.getName() + "】于" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "添加IP失败，失败信息：" + result.getMessage();
                        storageAccount.setStatus(AzureTaskStatus.AVAILABLE.name());
                        storageAccountRepository.update(storageAccount);
                    }
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                    //站内信推送
                    NotifyMessage notifyMessage = new NotifyMessage(context, "StorageAccount:", message, null,
                            true, false);
                    amqpTemplate.convertAndSend("event.notice.queue", notifyMessage);
                } catch (Exception e) {
                    logger.error("withAccessFromIpAddress storageAccount fail:", e);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate, MapTools.simpleMap(
                            "vendorId", vendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult<>(true, "任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("withAccessFromIpAddress storageAccount error!", e);
            return new BocloudResult<>(false, "更新失败:" + e.getMessage());
        }

    }

    @Override
    public BocloudResult<Void> withoutIpAddressAccess(StorageAccountFirewall entityParams, RequestContext context) {
        try {
            StorageAccountFirewall entity = storageAccountFirewallRepository.query(entityParams.getId());
            Assert.notNull(entity, "资源不存在");
            StorageAccount storageAccount = storageAccountRepository.query(entity.getStorageAccountId());
            Assert.notNull(storageAccount, "存储对象不存在");
            CloudVendor vendor = vendorRepository.query(storageAccount.getVendorId());
            Assert.notNull(vendor, "平台验证失败");

            StorageAccountFirewallModel model = new StorageAccountFirewallModel();
            model.setStorageAccountUuid(storageAccount.getUuid());
            model.setIpType(entity.getIpType());
            model.setIpAddresses(entity.getIpAddresses());

            //增加状态
            storageAccount.setStatus(AzureTaskStatus.IN_USE.name());
            storageAccountRepository.update(storageAccount);
            taskExecutor.execute(() -> {
                String operate = vendor.getType().toLowerCase() + ".storageaccount";
                String message = "存储对象删除IP失败";
                BocloudResult result = storageAccountDriver.withoutIpAddressAccess(vendor.getUuid(), storageAccount.getRegionId(), model);
                try {
                    if (result.isSuccess()) {
                        message = "尊敬的客户，您好！您的存储对象【" + storageAccount.getName() + "】于" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "删除IP成功，请登录控制台查看及管理。";
                        storageAccountFirewallRepository.remove(entityParams.getId());
                        storageAccount.setStatus(AzureTaskStatus.AVAILABLE.name());
                        storageAccountRepository.update(storageAccount);
                    } else {
                        logger.error("存储对象删除IP失败：" + result.getMessage());
                        message = "尊敬的客户，您好！您的存储对象【" + storageAccount.getName() + "】于" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "删除IP失败，失败信息：" + result.getMessage();
                        storageAccount.setStatus(AzureTaskStatus.AVAILABLE.name());
                        storageAccountRepository.update(storageAccount);
                    }
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                    //站内信推送
                    NotifyMessage notifyMessage = new NotifyMessage(context, "StorageAccount:", message, null,
                            true, false);
                    amqpTemplate.convertAndSend("event.notice.queue", notifyMessage);
                } catch (Exception e) {
                    logger.error("withoutIpAddressAccess storageAccount fail:", e);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate, MapTools.simpleMap(
                            "vendorId", vendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult<>(true, "任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("withoutIpAddressAccess storageAccount error!", e);
            return new BocloudResult<>(false, "更新失败:" + e.getMessage());
        }

    }

    private void withoutNetworkSubnets(StorageAccount storageAccount, CloudVendor vendor) {
        try {
            List<ResourceSubnetRelation> relations = resourceSubnetRelationRepository.listByResourceId(storageAccount.getId(), AzureSubnetRelationType.STORAGEACCOUNT.name());
            for (ResourceSubnetRelation relation : relations) {
                Subnet subnet = subnetRepository.query(relation.getSubnetId());
                StorageAccountModel model = new StorageAccountModel();
                model.setUuid(storageAccount.getUuid());
                model.setSubnetUuid(subnet.getSubnetUuid());
                BocloudResult result = storageAccountDriver.withoutNetworkSubnetAccess(vendor.getUuid(), storageAccount.getRegionId(), model);
                if (result.isSuccess()) {
                    logger.info("存储账户网络删除子网成功:{}", subnet.getName());
                    resourceSubnetRelationRepository.removeBySubnetIdAndResourceId(subnet.getId(), storageAccount.getId(), AzureSubnetRelationType.STORAGEACCOUNT.name());
                } else {
                    logger.info("存储账户网络删除子网失败:{}", subnet.getName());
                }

            }
        } catch (Exception e) {
            logger.error("存储账户网络删除子网报错", e);
        }
    }

    private void withoutIpAddress(StorageAccount storageAccount, CloudVendor vendor) {
        try {
            List<StorageAccountFirewall> firewalls = storageAccountFirewallRepository.listBySAId(storageAccount.getId());
            for (StorageAccountFirewall firewall : firewalls) {
                StorageAccountFirewallModel model = new StorageAccountFirewallModel();
                model.setStorageAccountUuid(storageAccount.getUuid());
                model.setIpType(firewall.getIpType());
                model.setIpAddresses(firewall.getIpAddresses());
                BocloudResult result = storageAccountDriver.withoutIpAddressAccess(vendor.getUuid(), storageAccount.getRegionId(), model);
                if (result.isSuccess()) {
                    logger.info("存储账户网络删除防火墙IP地址成功:{}", firewall.getIpAddresses());
                    storageAccountFirewallRepository.remove(firewall.getId());
                } else {
                    logger.info("存储账户网络删除防火墙IP地址失败:{}", firewall.getIpAddresses());
                }
            }
        } catch (Exception e) {
            logger.error("存储账户网络删除防火墙IP地址报错", e);
        }
    }

}