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

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.azure.db.CloudDatabaseDriver;
import com.bocloud.cmp.driver.azure.db.CloudDatabaseServerDriver;
import com.bocloud.cmp.driver.azure.db.DbConfigurationDriver;
import com.bocloud.cmp.entity.enums.ResourceCategory;
import com.bocloud.cmp.model.NotifyMessage;
import com.bocloud.cmp.model.azure.db.AzureDatabaseModel;
import com.bocloud.cmp.model.azure.db.AzureDatabaseServerModel;
import com.bocloud.cmp.model.azure.db.DbConfigurationModel;
import com.bocloud.cmp.model.azure.db.ServiceLevelObjectiveModel;
import com.bocloud.cmp.model.common.*;
import com.bocloud.cmp.params.azure.CloudDatabaseServerOperationParams;
import com.bocloud.common.encrypt.AESEncrptor;
import com.bocloud.common.encrypt.DESEncrptor;
import com.bocloud.common.encrypt.Encryptor;
import com.bocloud.common.model.*;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.DateTools;
import com.bocloud.common.utils.ListTool;
import com.bocloud.common.utils.MapTools;
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.ObjectRelation;
import com.bocloud.ims.entity.resource.ResourceGroup;
import com.bocloud.ims.entity.resource.azure.db.AzureDatabase;
import com.bocloud.ims.entity.resource.azure.db.AzureDatabaseServer;
import com.bocloud.ims.entity.resource.azure.db.DbConfiguration;
import com.bocloud.ims.entity.resource.azure.db.ServiceLevelObjective;
import com.bocloud.ims.interfaces.resource.azure.db.CloudDatabaseServerService;
import com.bocloud.ims.repository.resource.CloudVendorRepository;
import com.bocloud.ims.repository.resource.ObjectRelationRepository;
import com.bocloud.ims.repository.resource.ResourceGroupRepository;
import com.bocloud.ims.repository.resource.azure.db.CloudDatabaseRepository;
import com.bocloud.ims.repository.resource.azure.db.CloudDatabaseServerRepository;
import com.bocloud.ims.repository.resource.azure.db.DbConfigurationRepository;
import com.bocloud.ims.repository.resource.azure.db.ServiceLevelObjectiveRepository;
import com.bocloud.ims.service.internal.SmsProjectService;
import com.bocloud.ims.service.utils.ResourceEventPublisher;
import com.bocloud.nms.enums.OrderItemStatus;
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.ObjectUtils;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/**
 * @Company: 博云 www.bocloud.com
 * @ClassName: DatabaseForMysqlServiceImpl
 * @Description:
 * @author: zhenpingLi/李振平
 * @date: 2020/12/18 15:25
 */
@Service("cloudDatabaseServerService")
public class CloudDatabaseServerServiceImpl implements CloudDatabaseServerService {

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

    private static Logger logger = LoggerFactory.getLogger(CloudDatabaseServerServiceImpl.class);
    @Autowired
    private CloudVendorRepository vendorRepository;
    @Autowired
    private LockFactory lockFactory;
    @Autowired
    private ResourceGroupRepository resourceGroupRepository;
    @Autowired
    private CloudDatabaseServerRepository cloudDatabaseServerRepository;
    @Autowired
    private ServiceLevelObjectiveRepository serviceLevelObjectiveRepository;
    @Autowired
    private CloudDatabaseServerDriver cloudDatabaseServerDriver;
    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;
    @Autowired
    private ResourceEventPublisher resourceEventPublisher;
    @Autowired
    private SmsProjectService smsProjectService;
    @Autowired
    private CloudDatabaseDriver cloudDatabaseDriver;
    @Autowired
    private DbConfigurationDriver dbConfigurationDriver;
    @Autowired
    private CloudDatabaseRepository cloudDatabaseRepository;
    @Autowired
    private DbConfigurationRepository dbConfigurationRepository;
    @Autowired
    private AmqpTemplate amqpTemplate;
    @Autowired
    private ObjectRelationRepository objectRelationRepository;


    @Override
    public BocloudResult<Void> operations(CloudDatabaseServerOperationParams params, RequestContext context) {
        String action = params.getAction();
        if ("restart".equals(action)) {
            return this.restart(params, context);
        }
        if ("resetPassword".equals(action)) {
            return this.resetPassword(params, context);
        }
        if ("sslEnforcement".equals(action)) {
            return this.sslEnforcement(params, context);
        }
        if ("publicNetworkAccess".equals(action)) {
            return this.publicNetworkAccess(params, context);
        }
        return new BocloudResult<>(false, "Unknown Operation！");
    }

    @Override
    public BocloudResult<Void> create(AzureDatabaseServer entityParams, RequestContext context) {
        try {
            CloudVendor vendor = vendorRepository.query(entityParams.getVendorId());
            Assert.notNull(vendor, "平台验证失败");
            if (null != cloudDatabaseServerRepository.getByName(entityParams.getVendorId(), entityParams.getResourceGroupId(), entityParams.getName())) {
                return new BocloudResult<>(false, "名称已存在");
            }
            AzureDatabaseServerModel model = this.createMode(entityParams);
            entityParams.setCreatorId(context.getTarget());
            entityParams.setTenantId(context.getTenant());
            entityParams.setProjectId(context.getProject());
            if (context.getCatalog() == RequestContext.Catalog.User) {
                entityParams.setUserId(context.getTarget());
            }
            entityParams.setGmtCreate(new Date());
            entityParams.setStatus(AzureTaskStatus.BUILDING.name());
            cloudDatabaseServerRepository.save(entityParams);

            taskExecutor.execute(() -> {
                String operate = vendor.getType().toLowerCase() + ".databaseserver";
                String message = "创建数据库服务器失败";
                BocloudResult result = cloudDatabaseServerDriver.create(vendor.getUuid(), entityParams.getRegionId(), model);
                try {
                    if (result.isSuccess()) {
                        message = "尊敬的客户，您好！您的MySQL【" + entityParams.getName() + "】于" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "创建成功，请登录控制台查看及管理。";
                        AzureDatabaseServerModel newModel = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), AzureDatabaseServerModel.class);
                        BeanUtils.copyProperties(newModel, entityParams);
                        cloudDatabaseServerRepository.update(entityParams);
//                        BocloudResult result1 = cloudDatabaseDriver.list(vendor.getUuid(), entityParams.getRegionId(), newModel);
//                        if (result1.isSuccess()) {
//                            List<AzureDatabaseModel> databaseModels = JSONArray.parseArray(JSONArray.toJSONString(result1.getData()), AzureDatabaseModel.class);
//                            for (AzureDatabaseModel azureDatabaseModel : databaseModels) {
//                                AzureDatabase azureDatabase = new AzureDatabase();
//                                BeanUtils.copyProperties(azureDatabaseModel, azureDatabase);
//                                azureDatabase.setDatabaseServerId(entityParams.getId());
//                                cloudDatabaseRepository.save(azureDatabase);
//                            }
//                        }
                        BocloudResult result2 = dbConfigurationDriver.list(vendor.getUuid(), entityParams.getRegionId(), newModel);
                        if (result2.isSuccess()) {
                            List<DbConfigurationModel> dbConfigurationModels = JSONArray.parseArray(JSONArray.toJSONString(result2.getData()), DbConfigurationModel.class);
                            for (DbConfigurationModel dbConfigurationModel : dbConfigurationModels) {
                                DbConfiguration dbConfiguration = new DbConfiguration();
                                BeanUtils.copyProperties(dbConfigurationModel, dbConfiguration);
                                dbConfiguration.setDatabaseServerId(entityParams.getId());
                                dbConfigurationRepository.save(dbConfiguration);
                            }
                        }
                    } else {
                        logger.error("创建数据库服务器失败：" + result.getMessage());
                        message = "尊敬的客户，您好！您的MySQL【" + entityParams.getName() + "】于" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "创建失败，失败信息：" + result.getMessage();
                        cloudDatabaseServerRepository.remove(entityParams.getId());
                    }
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                    //站内信推送
                    NotifyMessage notifyMessage = new NotifyMessage(context, "MySQL:", message, null,
                            true, false);
                    amqpTemplate.convertAndSend("event.notice.queue", notifyMessage);
                } catch (Exception e) {
                    cloudDatabaseServerRepository.remove(entityParams.getId());
                    logger.error("create databaseServer 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 databaseServer error!", e);
            return new BocloudResult<>(false, "创建失败:" + e.getMessage());
        }
    }

    @Override
    public BocloudResult<Void> modify(AzureDatabaseServer entityParams, RequestContext context) {
        return null;
    }

    private AzureDatabaseServerModel createMode(AzureDatabaseServer entityParams) throws Exception {
        String createMode = entityParams.getCreateMode() == null ? "Default" : entityParams.getCreateMode();
        AzureDatabaseServerModel model;
        switch (createMode) {
            case "Default":
                model = this.createDefault(entityParams);
                break;
            case "Replica":
                model = this.createReplica(entityParams);
                break;
            case "GeoRestore":
                model = this.createGeoRestore(entityParams);
                break;
            case "PointInTimeRestore":
                model = this.createPointInTimeRestore(entityParams);
                break;
            default:
                model = this.createDefault(entityParams);
                break;
        }
        model.setCreateMode(createMode);
        return model;
    }

    private AzureDatabaseServerModel createDefault(AzureDatabaseServer entityParams) throws Exception {
        ResourceGroup resourceGroup = resourceGroupRepository.query(entityParams.getResourceGroupId());
        Assert.notNull(resourceGroup, "资源组不能为空");
        ServiceLevelObjective serviceLevelObjective = serviceLevelObjectiveRepository.query(entityParams.getSloId());
        Assert.notNull(serviceLevelObjective, "sku不能为空");
        ServiceLevelObjectiveModel sloModel = new ServiceLevelObjectiveModel();
        BeanUtils.copyProperties(serviceLevelObjective, sloModel);

        //密码加解密
        String administratorPassword = entityParams.getAdministratorPassword();
        Encryptor encryptor = new AESEncrptor();
        String newPassword = encryptor.decrypt(administratorPassword.trim(), null);
        logger.info("新密码明文：{}", newPassword);
        encryptor = new DESEncrptor();
        String dbPassword = encryptor.encrypt(newPassword, "BocloudCMP");
        logger.info("新密码密文：{}", dbPassword);
        entityParams.setAdministratorPassword(dbPassword);
        entityParams.setIsMaster(true);

        AzureDatabaseServerModel model = new AzureDatabaseServerModel();
        BeanUtils.copyProperties(entityParams, model);
        model.setResourceGroupName(resourceGroup.getName());
        model.setSloModel(sloModel);
        model.setAdministratorPassword(newPassword);
        logger.info("provider接受密码：{}", model.getAdministratorPassword());
        return model;
    }

    private AzureDatabaseServerModel createReplica(AzureDatabaseServer entityParams) throws Exception {
        ResourceGroup resourceGroup = resourceGroupRepository.query(entityParams.getResourceGroupId());
        Assert.notNull(resourceGroup, "资源组不能为空");
        AzureDatabaseServer masterServer = cloudDatabaseServerRepository.query(entityParams.getMasterServerId());
        Assert.notNull(masterServer, "主服务器不能为空");

        AzureDatabaseServerModel model = new AzureDatabaseServerModel();
        model.setName(entityParams.getName());
        model.setRegionId(entityParams.getRegionId());
        model.setMasterServerUuid(masterServer.getDatabaseServerUuid());
        model.setResourceGroupName(resourceGroup.getName());

        entityParams.setSloId(masterServer.getSloId());
        entityParams.setIsMaster(false);
        entityParams.setMasterServerId(masterServer.getId());
        return model;
    }

    private AzureDatabaseServerModel createGeoRestore(AzureDatabaseServer entityParams) throws Exception {
        ResourceGroup resourceGroup = resourceGroupRepository.query(entityParams.getResourceGroupId());
        Assert.notNull(resourceGroup, "资源组不能为空");
        ServiceLevelObjective serviceLevelObjective = serviceLevelObjectiveRepository.query(entityParams.getSloId());
        Assert.notNull(serviceLevelObjective, "sku不能为空");
        ServiceLevelObjectiveModel sloModel = new ServiceLevelObjectiveModel();
        BeanUtils.copyProperties(serviceLevelObjective, sloModel);
        AzureDatabaseServer masterServer = cloudDatabaseServerRepository.query(entityParams.getMasterServerId());
        Assert.notNull(masterServer, "主服务器不能为空");

        AzureDatabaseServerModel model = new AzureDatabaseServerModel();
        model.setName(entityParams.getName());
        model.setRegionId(entityParams.getRegionId());
        model.setMasterServerUuid(masterServer.getDatabaseServerUuid());
        model.setResourceGroupName(resourceGroup.getName());
        model.setSloModel(sloModel);

        entityParams.setIsMaster(true);
        return model;
    }

    private AzureDatabaseServerModel createPointInTimeRestore(AzureDatabaseServer entityParams) throws Exception {
        ResourceGroup resourceGroup = resourceGroupRepository.query(entityParams.getResourceGroupId());
        Assert.notNull(resourceGroup, "资源组不能为空");
        AzureDatabaseServer masterServer = cloudDatabaseServerRepository.query(entityParams.getMasterServerId());
        Assert.notNull(masterServer, "主服务器不能为空");
        AzureDatabaseServerModel model = new AzureDatabaseServerModel();
        model.setName(entityParams.getName());
        model.setRegionId(entityParams.getRegionId());
        model.setMasterServerUuid(masterServer.getDatabaseServerUuid());
        model.setResourceGroupName(resourceGroup.getName());
        model.setRestorePointInTime(entityParams.getRestorePointInTime());
        model.setInfrastructureEncryption(entityParams.getInfrastructureEncryption());

        entityParams.setSloId(masterServer.getSloId());
        entityParams.setIsMaster(true);
        return model;
    }


    @Override
    public BocloudResult<Void> remove(Long id, RequestContext context) {
        String path = AzureDatabaseServer.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            AzureDatabaseServer entity = cloudDatabaseServerRepository.query(id);
            Assert.notNull(entity, "数据不存在");
            CloudVendor vendor = vendorRepository.query(entity.getVendorId());
            Assert.notNull(vendor, "平台验证失败");
            ResourceGroup resourceGroup = resourceGroupRepository.query(entity.getResourceGroupId());
            Assert.notNull(resourceGroup, "资源组不能为空");
            AzureDatabaseServerModel model = new AzureDatabaseServerModel();
            model.setResourceGroupName(resourceGroup.getName());
            model.setName(entity.getName());
            model.setType(entity.getType());

            entity.setStatus(AzureTaskStatus.DELETING.name());
            cloudDatabaseServerRepository.update(entity);
            taskExecutor.execute(() -> {
                String operate = vendor.getType().toLowerCase() + ".databaseserver";
                String message = "删除数据库服务器失败";
                BocloudResult result = cloudDatabaseServerDriver.remove(vendor.getUuid(), entity.getRegionId(), model);
                try {
                    if (result.isSuccess()) {
                        message = "删除数据库服务器成功";
                        cloudDatabaseServerRepository.remove(id, context.getTarget());
                        logger.info("删除数据库服务器成功: {} ,操作人ID:{}", entity.getName(), 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));
                    //站内信推送
                    NotifyMessage notifyMessage = new NotifyMessage(context, "提示:", message, null,
                            true, false);
                    amqpTemplate.convertAndSend("event.notice.queue", notifyMessage);
                } catch (Exception e) {
                    logger.error("remove databaseServer 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 databaseServer error!", e);
            return new BocloudResult<>(false, "删除失败:" + e.getMessage());
        }
    }

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

    @Override
    public BocloudResult<Void> pricingLayer(AzureDatabaseServer modifyParams, RequestContext context) {
        try {
            AzureDatabaseServer entity = cloudDatabaseServerRepository.query(modifyParams.getId());
            Assert.notNull(entity, "资源不存在");
            CloudVendor vendor = vendorRepository.query(entity.getVendorId());
            Assert.notNull(vendor, "平台验证失败");
            ResourceGroup resourceGroup = resourceGroupRepository.query(entity.getResourceGroupId());
            Assert.notNull(resourceGroup, "资源组不能为空");
            ServiceLevelObjective serviceLevelObjective = serviceLevelObjectiveRepository.query(modifyParams.getSloId());
            Assert.notNull(serviceLevelObjective, "sku不能为空");
            ServiceLevelObjectiveModel sloModel = new ServiceLevelObjectiveModel();
            BeanUtils.copyProperties(serviceLevelObjective, sloModel);

            AzureDatabaseServerModel model = new AzureDatabaseServerModel();
            model.setName(entity.getName());
            model.setRegionId(entity.getRegionId());
            model.setResourceGroupName(resourceGroup.getName());
            model.setSloModel(sloModel);
            model.setStorageMb(modifyParams.getStorageMb());
            model.setBackupRetentionDays(modifyParams.getBackupRetentionDays());
            model.setStorageAutogrow(modifyParams.getStorageAutogrow());
            entity.setStatus(AzureTaskStatus.UPDATING.name());
            cloudDatabaseServerRepository.update(entity);

            taskExecutor.execute(() -> {
                String operate = vendor.getType().toLowerCase() + ".databaseserver";
                String message = "数据库服务器调整配置失败";
                BocloudResult result = cloudDatabaseServerDriver.pricingLayer(vendor.getUuid(), entity.getRegionId(), model);
                try {
                    if (result.isSuccess()) {
                        message = "尊敬的客户，您好！您的MySQL【" + entity.getName() + "】于" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "调整配置成功，请登录控制台查看及管理。";
                        entity.setSloId(modifyParams.getSloId());
                        entity.setStorageMb(modifyParams.getStorageMb());
                        entity.setBackupRetentionDays(modifyParams.getBackupRetentionDays());
                        entity.setStorageAutogrow(modifyParams.getStorageAutogrow());
                        entity.setStatus(AzureTaskStatus.Ready.name());
                        cloudDatabaseServerRepository.update(entity);
                    } else {
                        logger.error("数据库服务器调整配置失败：" + result.getMessage());
                        message = "尊敬的客户，您好！您的MySQL【" + entity.getName() + "】于" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "调整配置失败，失败信息：" + result.getMessage();
                        entity.setStatus(AzureTaskStatus.Ready.name());
                        cloudDatabaseServerRepository.update(entity);
                    }
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                    //站内信推送
                    NotifyMessage notifyMessage = new NotifyMessage(context, "MySQL:", message, null,
                            true, false);
                    amqpTemplate.convertAndSend("event.notice.queue", notifyMessage);
                } catch (Exception e) {
                    entity.setStatus(AzureTaskStatus.Ready.name());
                    cloudDatabaseServerRepository.update(entity);
                    logger.error("pricingLayer databaseServer 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("pricingLayer databaseServer error!", e);
            return new BocloudResult<>(false, "调整配置失败:" + e.getMessage());
        }
    }

    @Override
    public BocloudResult<Void> apply(ApplicationParam param) {
        try {
            Assert.notNull(param, "参数格式错误");
            ServiceOrder order = param.getOrder();
            Assert.notNull(order, "订单不存在");
            List<OrderItem> items = order.getItems();
            Assert.notEmpty(items, "订单明细不存在");
            List<ElementModel> elements = param.getElements();
            // 申请人
            RequestContext context = param.getContext();
            Assert.notNull(context, "申请人不存在");
            // 位置
            LocationModel location = param.getLocation();
            // 订购信息
            EmptionModel emption = param.getEmption();
            // 使用时长信息
            DurationModel duration = emption.getDuration();
            // 使用时长单位Hour/Month
            DurationModel.Mode mode = duration.getMode();
            // 时长
            Integer month = duration.getAmount();
            // 申请个数
            Integer count = null == emption.getCount() ? 1 : emption.getCount();
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new Date());
            if (DurationModel.Mode.Hour == mode) {
                calendar.setTime(DateTools.stringToDateTime("2099-12-31 00:00:00"));
            } else {
                calendar.add(Calendar.MONTH, month);
            }
            CloudVendor vendor = vendorRepository.query(location.getVendorId());
            Assert.notNull(vendor, "当前可用域未绑定云平台");
            logger.info("apply mysql start...");
            // 前端传递的单个配置信息
            JSONObject configs = param.getConfigs();
            // 由单个信息进行批处理转换
            List<AzureDatabaseServer> processEntity = new ArrayList<>();
            for (int i = 0; i < count; i++) {
                JSONObject newObj = JSONObject.parseObject(configs.toJSONString());
                AzureDatabaseServer newEntity = JSONObject.parseObject(newObj.toJSONString(), AzureDatabaseServer.class);
                processEntity.add(newEntity);
            }

            List<QuotaBean> quotas = param.getQuotas();
            taskExecutor.execute(() -> {
                //结果集合
                List<Future<BocloudResult>> futures = new ArrayList<>();
                // 创建成功的资源集合
                List<BocloudResult> successList = new ArrayList<>();
                // 创建失败的资源集合
                List<BocloudResult> failureList = new ArrayList<>();
                try {
                    //执行创建
                    for (AzureDatabaseServer entity : processEntity) {
                        futures.add(taskExecutor.submit(() -> this.applyCreate(entity, context)));
                    }
                    //获取线程池返回接口
                    for (int i = 0; i < futures.size(); i++) {
                        List<ResourceModel> resources = new ArrayList<>();
                        // 通知订单
                        OrderMessage message = null;
                        OrderItem item = items.get(i);
                        BocloudResult result = futures.get(i).get();
                        if (result.isSuccess()) {
                            AzureDatabaseServer newEntity = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), AzureDatabaseServer.class);
                            ObjectRelation relation = new ObjectRelation(context.getTarget(), newEntity.getId(),
                                    false, ResourceCategory.MySQL.name(), context.getCatalog().name(), 0);
                            relation.setExpiredTime(calendar.getTime());
                            objectRelationRepository.save(relation);
                            newEntity.setUuid(item.getSn());
                            newEntity.setGmtModify(new Date());
                            newEntity.setMenderId(context.getTarget());
                            cloudDatabaseServerRepository.update(newEntity);

                            BocloudResult bocloudResult = new BocloudResult(true,
                                    "【" + newEntity.getName() + "】创建成功【" + result.getMessage() + "】");
                            successList.add(bocloudResult);
                            resources.add(new ResourceModel(newEntity.getName(), newEntity.getDatabaseServerUuid(),
                                    param.getService(), newEntity.getDatabaseServerUuid(), param.getOrder().getSn()));
                            message = new OrderMessage(item.getSn(), OrderMessage.Operation.Application,
                                    OrderItemStatus.OpenedSuccess, null, "MySql申请创建成功", newEntity.getGmtCreate(),
                                    calendar.getTime(), resources, ResourceCategory.MySQL.name(), context);
                            message.setCategory(ResourceCategory.MySQL.name());
                            // 通知订单
                            amqpTemplate.convertAndSend("resource.result.queue", message);

                        } else {
                            BocloudResult bocloudResult = new BocloudResult(true, "创建失败【" + result.getMessage() + "】");
                            failureList.add(bocloudResult);
                            message = new OrderMessage(item.getSn(), OrderMessage.Operation.Application,
                                    OrderItemStatus.OpenedFailure, null, result.getMessage(), null, null, resources,
                                    ResourceCategory.MySQL.name(), context);
                            // 回滚配额
                            List<QuotaBean> beans = new ArrayList<>();
                            for (QuotaBean bean : quotas) {
                                beans.add(new QuotaBean(bean.getCode(), bean.getValue() / items.size()));
                            }
                            message.setQuotas(beans);
                            message.setCategory(ResourceCategory.MySQL.name());
                            // 通知订单
                            amqpTemplate.convertAndSend("resource.result.queue", message);
                        }
                    }
                } catch (Exception e) {
                    logger.error("apply MySql fail:", e);
                }
            });
            // 发送给云平台统计队列对云平台重新统计
            JSONObject jsonObject = new JSONObject();
            jsonObject.put(Common.VENDORID, vendor.getId());
            amqpTemplate.convertAndSend("vendor.statistics.queue", jsonObject);
            logger.info("Apply MySql end");
            return new BocloudResult<>(true, "申请任务已经下发，正在执行……");
        } catch (Exception e) {
            logger.error("Apply MySql error", e);
            return new BocloudResult<>(false, "申请MySql失败：" + e.getMessage());
        }
    }

    @Override
    public BocloudResult<Void> extension(ExtensionParam param) {
        try {
            AzureDatabaseServer entity = cloudDatabaseServerRepository.getByUuid(param.getInstance());
            Assert.notNull(entity, "MySql不存在");
            ObjectRelation relation = objectRelationRepository.get(entity.getId(), ResourceCategory.MySQL.name());
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(relation.getExpiredTime());
            calendar.add(Calendar.MONTH, param.getExtension());
            objectRelationRepository.updateExpriedTime(entity.getId(), calendar.getTime(),
                    ResourceCategory.MySQL.name(), param.getContext().getCatalog().name());
            OrderMessage message = new OrderMessage();
            message.setSn(param.getInstance());
            message.setOperation(OrderMessage.Operation.Extension);
            message.setStatus(OrderItemStatus.ExtensionSuccess);
            message.setExtension(param.getExtension());
            message.setExpiredTime(calendar.getTime());
            message.setCategory(ResourceCategory.MySQL.name());
            message.setMessage("MySql延期成功");
            amqpTemplate.convertAndSend("resource.result.queue", message);
            return new BocloudResult<>(true, "MySql延期成功");
        } catch (Exception e) {
            logger.error("Get error message：{}", e.getMessage());
            return new BocloudResult<>(false, "MySql延期失败：" + e.getMessage());
        }
    }

    @Override
    public BocloudResult<Void> cancelation(CancelationParam param) {
        try {
            AzureDatabaseServer entity = cloudDatabaseServerRepository.getByUuid(param.getInstance());
            Assert.notNull(entity, "MySql不存在");
            RequestContext context = param.getContext();
            BocloudResult result = this.remove(entity.getId(), context);
            Assert.isTrue(result.isSuccess(), result.getMessage());
            OrderMessage message = new OrderMessage();
            message.setSn(param.getInstance());
            message.setOperation(OrderMessage.Operation.Cancelation);
            message.setStatus(OrderItemStatus.UnsubscribeSuccess);
            message.setCategory(ResourceCategory.MySQL.name());
            message.setMessage("MySql删除成功");
            message.setQuotas(new ArrayList<>());
            message.setResources(new ArrayList<>());
            message.setContext(context);
            amqpTemplate.convertAndSend("resource.result.queue", message);
            return new BocloudResult<>(true, "MySql删除成功");
        } catch (Exception e) {
            logger.error("Get error message：{}", e.getMessage());
            return new BocloudResult<>(false, e.getMessage());
        }
    }

    @Override
    public BocloudResult<GridBean<AzureDatabaseServer>> 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);
        try {
            GridBean<AzureDatabaseServer> gridBean;
            List<AzureDatabaseServer> list;
            int total;
            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.cloudDatabaseServerRepository.count(params, null, projectIds, null);
                list = this.cloudDatabaseServerRepository.list(page, rows, params, sorter, null, projectIds, null);
            } else {
                list = cloudDatabaseServerRepository.list(page, rows, params, sorter);
                total = cloudDatabaseServerRepository.count(params);
            }
            for (AzureDatabaseServer entity : list) {
                ServiceLevelObjective serviceLevelObjective = serviceLevelObjectiveRepository.query(entity.getSloId());
                if (!ObjectUtils.isEmpty(serviceLevelObjective)) {
                    entity.setServiceLevelObjective(serviceLevelObjective);
                }
            }
            gridBean = new GridBean<>(page, rows, total, list);
            return new BocloudResult<>(true, gridBean, "查询成功");
        } catch (Exception e) {
            logger.error("list databaseServer failure:", e);
            return new BocloudResult<>(false, "查询失败:" + e.getMessage());
        }

    }

    public BocloudResult<AzureDatabaseServer> detail(Long id, RequestContext context) {
        try {
            AzureDatabaseServer entity = cloudDatabaseServerRepository.query(id);
            Assert.notNull(entity, "数据不存在");
            ServiceLevelObjective serviceLevelObjective = serviceLevelObjectiveRepository.query(entity.getSloId());
            if (!ObjectUtils.isEmpty(serviceLevelObjective)) {
                entity.setServiceLevelObjective(serviceLevelObjective);
            }
            return new BocloudResult<>(true, entity, "查询详情成功");
        } catch (Exception e) {
            logger.error("query databaseServer error!", e);
            return new BocloudResult<>(false, "查询详情失败:" + e.getMessage());
        }
    }

    public BocloudResult<Void> modify(Long id, String params, RequestContext context) {
        return null;
    }

    public BocloudResult<Void> restart(CloudDatabaseServerOperationParams params, RequestContext context) {
        try {
            Long id = params.getId();
            AzureDatabaseServer entity = cloudDatabaseServerRepository.query(id);
            Assert.notNull(entity, "数据不存在");
            CloudVendor vendor = vendorRepository.query(entity.getVendorId());
            Assert.notNull(vendor, "平台验证失败");
            ResourceGroup resourceGroup = resourceGroupRepository.query(entity.getResourceGroupId());
            Assert.notNull(resourceGroup, "资源组不能为空");
            entity.setStatus("Restarting");
            cloudDatabaseServerRepository.update(entity);
            AzureDatabaseServerModel model = new AzureDatabaseServerModel();
            model.setResourceGroupName(resourceGroup.getName());
            model.setName(entity.getName());
            taskExecutor.execute(() -> {
                String operate = vendor.getType().toLowerCase() + ".databaseserver";
                String message = "重启数据库服务器失败";
                BocloudResult result = cloudDatabaseServerDriver.restart(vendor.getUuid(), entity.getRegionId(), model);
                try {
                    if (result.isSuccess()) {
                        message = "重启数据库服务器成功";
                        AzureDatabaseServerModel newModel = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), AzureDatabaseServerModel.class);
                        entity.setStatus(newModel.getStatus());
                        cloudDatabaseServerRepository.update(entity);
                    } else {
                        logger.error("重启数据库服务器失败：" + result.getMessage());
                        message = result.getMessage();
                        entity.setStatus("Ready");
                        cloudDatabaseServerRepository.update(entity);
                    }
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                } catch (Exception e) {
                    logger.error("restart databaseServer fail:", e);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                    entity.setStatus("Ready");
                    cloudDatabaseServerRepository.update(entity);
                }
            });
            return new BocloudResult<>(true, "任务已下发，正在执行...");
        } catch (Exception e) {
            logger.error("restart databaseServer error!", e);
            return new BocloudResult<>(false, "重启失败:" + e.getMessage());
        }
    }

    public BocloudResult<Void> resetPassword(CloudDatabaseServerOperationParams params, RequestContext context) {
        try {
            Long id = params.getId();
            String administratorPassword = params.getAdministratorPassword();
            //密码加解密
            Encryptor encryptor = new AESEncrptor();
            String newPassword = encryptor.decrypt(administratorPassword.trim(), null);
            logger.info("新密码明文：{}", newPassword);
            encryptor = new DESEncrptor();
            String dbPassword = encryptor.encrypt(newPassword, "BocloudCMP");
            logger.info("新密码密文：{}", dbPassword);

            AzureDatabaseServer entity = cloudDatabaseServerRepository.query(id);
            Assert.notNull(entity, "数据不存在");
            CloudVendor vendor = vendorRepository.query(entity.getVendorId());
            Assert.notNull(vendor, "平台验证失败");
            ResourceGroup resourceGroup = resourceGroupRepository.query(entity.getResourceGroupId());
            Assert.notNull(resourceGroup, "资源组不能为空");
            AzureDatabaseServerModel model = new AzureDatabaseServerModel();
            model.setResourceGroupName(resourceGroup.getName());
            model.setName(entity.getName());
            model.setAdministratorPassword(newPassword);
            taskExecutor.execute(() -> {
                String operate = vendor.getType().toLowerCase() + ".databaseserver";
                String message = "修改数据库服务器失败";
                BocloudResult result = cloudDatabaseServerDriver.modify(vendor.getUuid(), entity.getRegionId(), model);
                try {
                    if (result.isSuccess()) {
                        message = "修改数据库服务器成功";
                        AzureDatabaseServerModel newModel = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), AzureDatabaseServerModel.class);
                        entity.setAdministratorPassword(dbPassword);
                        cloudDatabaseServerRepository.update(entity);
                    } 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("resetPassword databaseServer 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("resetPassword databaseServer error!", e);
            return new BocloudResult<>(false, "重启失败:" + e.getMessage());
        }
    }

    public BocloudResult<Void> sslEnforcement(CloudDatabaseServerOperationParams params, RequestContext context) {
        try {
            Long id = params.getId();
            String sslEnforcement = params.getSslEnforcement();
            String minimalTlsVersion = params.getMinimalTlsVersion();
            AzureDatabaseServer entity = cloudDatabaseServerRepository.query(id);
            Assert.notNull(entity, "数据不存在");
            CloudVendor vendor = vendorRepository.query(entity.getVendorId());
            Assert.notNull(vendor, "平台验证失败");
            ResourceGroup resourceGroup = resourceGroupRepository.query(entity.getResourceGroupId());
            Assert.notNull(resourceGroup, "资源组不能为空");
            AzureDatabaseServerModel model = new AzureDatabaseServerModel();
            model.setResourceGroupName(resourceGroup.getName());
            model.setName(entity.getName());
            model.setSslEnforcement(sslEnforcement);
            model.setMinimalTlsVersion(minimalTlsVersion);
            taskExecutor.execute(() -> {
                String operate = vendor.getType().toLowerCase() + ".databaseserver";
                String message = "修改连接安全性失败";
                BocloudResult result = cloudDatabaseServerDriver.modify(vendor.getUuid(), entity.getRegionId(), model);
                try {
                    if (result.isSuccess()) {
                        message = "修改连接安全性成功";
                        AzureDatabaseServerModel newModel = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), AzureDatabaseServerModel.class);
                        entity.setSslEnforcement(newModel.getSslEnforcement());
                        if (newModel.getSslEnforcement().equals("Enabled")) {
                            entity.setMinimalTlsVersion(minimalTlsVersion);
                        } else {
                            entity.setMinimalTlsVersion(null);
                        }
                        cloudDatabaseServerRepository.update(entity);
                    } 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("sslEnforcement databaseServer 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("sslEnforcement databaseServer error!", e);
            return new BocloudResult<>(false, "修改连接安全性失败:" + e.getMessage());
        }
    }

    public BocloudResult<Void> publicNetworkAccess(CloudDatabaseServerOperationParams params, RequestContext context) {
        try {
            Long id = params.getId();
            String publicNetworkAccess = params.getPublicNetworkAccess();
            AzureDatabaseServer entity = cloudDatabaseServerRepository.query(id);
            Assert.notNull(entity, "数据不存在");
            CloudVendor vendor = vendorRepository.query(entity.getVendorId());
            Assert.notNull(vendor, "平台验证失败");
            ResourceGroup resourceGroup = resourceGroupRepository.query(entity.getResourceGroupId());
            Assert.notNull(resourceGroup, "资源组不能为空");
            AzureDatabaseServerModel model = new AzureDatabaseServerModel();
            model.setResourceGroupName(resourceGroup.getName());
            model.setName(entity.getName());
            model.setPublicNetworkAccess(publicNetworkAccess);
            taskExecutor.execute(() -> {
                String operate = vendor.getType().toLowerCase() + ".databaseserver";
                String message = "修改数据库服务器失败";
                BocloudResult result = cloudDatabaseServerDriver.modify(vendor.getUuid(), entity.getRegionId(), model);
                try {
                    if (result.isSuccess()) {
                        message = "修改数据库服务器成功";
                        AzureDatabaseServerModel newModel = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), AzureDatabaseServerModel.class);
                        entity.setPublicNetworkAccess(newModel.getPublicNetworkAccess());
                        cloudDatabaseServerRepository.update(entity);
                    } 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("publicNetworkAccess databaseServer 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("publicNetworkAccess databaseServer error!", e);
            return new BocloudResult<>(false, "重启失败:" + e.getMessage());
        }
    }

    public BocloudResult<Void> applyCreate(AzureDatabaseServer entityParams, RequestContext context) {
        try {
            CloudVendor vendor = vendorRepository.query(entityParams.getVendorId());
            Assert.notNull(vendor, "平台验证失败");
            if (null != cloudDatabaseServerRepository.getByName(entityParams.getVendorId(), entityParams.getResourceGroupId(), entityParams.getName())) {
                return new BocloudResult<>(false, "名称已存在");
            }
            AzureDatabaseServerModel model = this.createMode(entityParams);

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

            BocloudResult result = cloudDatabaseServerDriver.create(vendor.getUuid(), entityParams.getRegionId(), model);
            if (result.isSuccess()) {
                AzureDatabaseServerModel newModel = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), AzureDatabaseServerModel.class);
                BeanUtils.copyProperties(newModel, entityParams);
                cloudDatabaseServerRepository.update(entityParams);
                BocloudResult result1 = cloudDatabaseDriver.list(vendor.getUuid(), entityParams.getRegionId(), newModel);
                if (result1.isSuccess()) {
                    List<AzureDatabaseModel> databaseModels = JSONArray.parseArray(JSONArray.toJSONString(result1.getData()), AzureDatabaseModel.class);
                    for (AzureDatabaseModel azureDatabaseModel : databaseModels) {
                        AzureDatabase azureDatabase = new AzureDatabase();
                        BeanUtils.copyProperties(azureDatabaseModel, azureDatabase);
                        azureDatabase.setDatabaseServerId(entityParams.getId());
                        cloudDatabaseRepository.save(azureDatabase);
                    }
                }
                BocloudResult result2 = dbConfigurationDriver.list(vendor.getUuid(), entityParams.getRegionId(), newModel);
                if (result2.isSuccess()) {
                    List<DbConfigurationModel> dbConfigurationModels = JSONArray.parseArray(JSONArray.toJSONString(result2.getData()), DbConfigurationModel.class);
                    for (DbConfigurationModel dbConfigurationModel : dbConfigurationModels) {
                        DbConfiguration dbConfiguration = new DbConfiguration();
                        BeanUtils.copyProperties(dbConfigurationModel, dbConfiguration);
                        dbConfiguration.setDatabaseServerId(entityParams.getId());
                        dbConfigurationRepository.save(dbConfiguration);
                    }
                }
                return new BocloudResult(true, entityParams, "创建成功！");
            } else {
                logger.error("创建数据库服务器失败：" + result.getMessage());
                cloudDatabaseServerRepository.remove(entityParams.getId());
                return new BocloudResult<>(false, "创建失败:" + result.getMessage());
            }
        } catch (Exception e) {
            logger.error("create databaseServer error!", e);
            return new BocloudResult<>(false, "创建失败:" + e.getMessage());
        }
    }
}