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

import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.azure.tags.TagDriver;
import com.bocloud.cmp.entity.enums.azure.AzureConsumedServiceEnum;
import com.bocloud.cmp.model.azure.tags.TagModel;
import com.bocloud.cmp.params.azure.AzureTagsParams;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.RequestContext;
import com.bocloud.ims.entity.resource.*;
import com.bocloud.ims.entity.resource.azure.AvailabilitySet;
import com.bocloud.ims.entity.resource.azure.account.StorageAccount;
import com.bocloud.ims.entity.resource.azure.db.AzureDatabaseServer;
import com.bocloud.ims.entity.resource.azure.ddos.DdosProtectionPlan;
import com.bocloud.ims.entity.resource.azure.network.PublicIPAddress;
import com.bocloud.ims.entity.resource.azure.network.RouterTable;
import com.bocloud.ims.entity.resource.azure.redis.CloudRedis;
import com.bocloud.ims.entity.resource.azure.slb.Slb;
import com.bocloud.ims.interfaces.resource.azure.tags.AzureTagService;
import com.bocloud.ims.repository.resource.*;
import com.bocloud.ims.repository.resource.azure.AvailabilitySetRepository;
import com.bocloud.ims.repository.resource.azure.account.StorageAccountRepository;
import com.bocloud.ims.repository.resource.azure.db.CloudDatabaseServerRepository;
import com.bocloud.ims.repository.resource.azure.ddos.DdosProtectionPlanRepository;
import com.bocloud.ims.repository.resource.azure.network.PublicIPAddressRepository;
import com.bocloud.ims.repository.resource.azure.network.RouterTableRepository;
import com.bocloud.ims.repository.resource.azure.redis.CloudRedisRepository;
import com.bocloud.ims.repository.resource.azure.slb.SlbRepository;
import com.bocloud.ims.service.resource.azure.slb.BackEndServiceImpl;
import com.mysql.cj.result.LongValueFactory;
import lombok.extern.log4j.Log4j;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;

/**
 * @Company: 博云 www.bocloud.com
 * @ClassName: TagServiceImpl
 * @Description:
 * @author: zhenpingLi/李振平
 * @date: 2021/6/7 20:00
 */
@Service
public class AzureTagServiceImpl implements AzureTagService {

    private static Logger logger = LoggerFactory.getLogger(AzureTagServiceImpl.class);
    @Autowired
    private CloudVendorRepository vendorRepository;
    @Autowired
    private TagDriver tagDriver;
    @Autowired
    private StorageAccountRepository storageAccountRepository;
    @Autowired
    private CloudServerRepository cloudServerRepository;
    @Autowired
    private PublicIPAddressRepository publicIPAddressRepository;
    @Autowired
    private ImageRepository imageRepository;
    @Autowired
    private VolumeRepository volumeRepository;
    @Autowired
    private SnapshotRepository snapshotRepository;
    @Autowired
    private SecurityGroupRepository securityGroupRepository;

    @Autowired
    private VpcRepository vpcRepository;
    @Autowired
    private ResourceGroupRepository resourceGroupRepository;
    @Autowired
    private NetworkInterfaceRepository networkInterfaceRepository;
    @Autowired
    private AvailabilitySetRepository availabilitySetRepository;
    @Autowired
    private SlbRepository slbRepository;
    @Autowired
    private RouterTableRepository routerTableRepository;
    @Autowired
    private CloudRedisRepository redisRepository;
    @Autowired
    private CloudDatabaseServerRepository mysqlRepository;
    @Autowired
    private KeypairRepository keypairRepository;
    @Autowired
    private DdosProtectionPlanRepository ddosProtectionPlanRepository;

    @Override
    public BocloudResult tags(AzureTagsParams params, RequestContext context) {
        try {
            long start,end;
            start = System.currentTimeMillis();
            logger.info("开始分配标签");
            String action = params.getAction();
            Long resourceId = params.getResourceId();
            String tags = params.getTags();
            AzureConsumedServiceEnum serviceEnum = AzureConsumedServiceEnum.valueOf(action);
            TagModel tagModel = this.getTagModel(serviceEnum, resourceId, tags);
            logger.info("TagModel:{}",JSONObject.toJSONString(tagModel));
            CloudVendor vendor = vendorRepository.query(tagModel.getVendorId());
            Assert.notNull(vendor, "平台不存在");
            logger.info("平台验证通过，执行分配标签");
            BocloudResult result = tagDriver.tags(vendor.getUuid(), tagModel.getRegionId(), tagModel);
            logger.info("分配标签完成");
            end = System.currentTimeMillis();
            logger.info("start time:" + start+ "; end time:" + end+ "; Run Time:" + (end - start) + "(ms)");
            if (result.isFailed()) {
                return result;
            }
            logger.info("更新数据");
            this.saveDatabase(serviceEnum, resourceId, tagModel.getTagMap());
            return new BocloudResult(true, "更新成功！");
        } catch (Exception e) {
            logger.error("update tags error:", e);
            return new BocloudResult(false, "更新标签失败:" + e.getMessage());
        }
    }

    private TagModel getTagModel(AzureConsumedServiceEnum serviceEnum, Long resourceId, String tags) {
        String resourceUuid = null;
        String resourceName = null;
        String resourceGroupName = null;
        Long vendorId = null;
        String regionId = null;
        Map<String, String> tagMap;

        if (StringUtils.isEmpty(tags)) {
            tagMap = new HashMap<>();
        } else {
            tagMap = JSONObject.parseObject(tags, Map.class);
        }

        switch (serviceEnum) {
            case STORAGEACCOUNT:
                StorageAccount storageAccount = storageAccountRepository.query(resourceId);
                resourceUuid = storageAccount.getUuid();
                vendorId = storageAccount.getVendorId();
                regionId = storageAccount.getRegionId();
                break;
            case VM:
                CloudServer cloudServer = cloudServerRepository.query(resourceId);
                resourceUuid = cloudServer.getInstanceId();
                vendorId = cloudServer.getVendorId();
                regionId = cloudServer.getRegionId();
                break;
            case EIP:
                PublicIPAddress eip = publicIPAddressRepository.query(resourceId);
                resourceUuid = eip.getUuid();
                vendorId = eip.getVendorId();
                regionId = eip.getRegionId();
                break;
            case ROUTERTABLE:
                RouterTable routerTable = routerTableRepository.query(resourceId);
                resourceUuid = routerTable.getUuid();
                vendorId = routerTable.getVendorId();
                regionId = routerTable.getRegionId();
                break;
            case VPC:
                Vpc vpc = vpcRepository.query(resourceId);
                resourceUuid = vpc.getVpcId();
                vendorId = vpc.getVendorId();
                regionId = vpc.getRegionId();
                break;
            case ASET:
                AvailabilitySet aset = availabilitySetRepository.query(resourceId);
                resourceUuid = aset.getUuid();
                vendorId = aset.getVendorId();
                regionId = aset.getRegionId();
                break;
            case SNAPSHOT:
                Snapshot snapshot = snapshotRepository.query(resourceId);
                resourceUuid = snapshot.getSnapshotUuid();
                vendorId = snapshot.getVendorId();
                regionId = snapshot.getRegionId();
                break;
            case VOLUME:
                Volume volume = volumeRepository.query(resourceId);
                resourceUuid = volume.getVolumeUuid();
                vendorId = volume.getVendorId();
                regionId = volume.getRegionId();
                break;
            case SLB:
                Slb slb = slbRepository.query(resourceId);
                resourceUuid = slb.getUuid();
                vendorId = slb.getVendorId();
                regionId = slb.getRegionId();
                break;
            case RESOURCEGROUP:
                ResourceGroup resourceGroup = resourceGroupRepository.query(resourceId);
                vendorId = resourceGroup.getVendorId();
                regionId = resourceGroup.getRegionId();
                resourceName = resourceGroup.getName();
                break;
            case NICS:
                NetworkInterface nics = networkInterfaceRepository.query(resourceId);
                resourceUuid = nics.getNetworkInterfaceUuid();
                vendorId = nics.getVendorId();
                regionId = nics.getRegionId();
                break;
            case SECURITYGROUP:
                SecurityGroup securityGroup = securityGroupRepository.query(resourceId);
                resourceUuid = securityGroup.getGroupUuid();
                vendorId = securityGroup.getVendorId();
                regionId = securityGroup.getRegionId();
                break;
            case MYSQL:
                AzureDatabaseServer mysql = mysqlRepository.query(resourceId);
                resourceName = mysql.getName();
                resourceGroupName = mysql.getResourceGroupName();
                vendorId = mysql.getVendorId();
                regionId = mysql.getRegionId();
                break;
            case REDIS:
                CloudRedis redis = redisRepository.query(resourceId);
                resourceName = redis.getName();
                resourceGroupName = redis.getResourceGroupName();
                vendorId = redis.getVendorId();
                regionId = redis.getRegionId();
                break;
            case KEYPAIR:
                Keypair keypair = keypairRepository.query2(resourceId);
                resourceName = keypair.getName();
                resourceGroupName = keypair.getResourceGroupName();
                vendorId = keypair.getVendorId();
                regionId = keypair.getRegionId();
                break;
            case DDOS:
                DdosProtectionPlan ddosProtectionPlan = ddosProtectionPlanRepository.query(resourceId);
                resourceName = ddosProtectionPlan.getName();
                resourceGroupName = ddosProtectionPlan.getResourceGroupName();
                vendorId = ddosProtectionPlan.getVendorId();
                regionId = ddosProtectionPlan.getRegionId();
                break;
            default:
                break;
        }
        TagModel model = new TagModel();
        model.setResourceGroupName(resourceGroupName);
        model.setResourceName(resourceName);
        model.setResourceUuid(resourceUuid);
        model.setTagMap(tagMap);
        model.setVendorId(vendorId);
        model.setRegionId(regionId);
        model.setAction(serviceEnum.name());
        return model;
    }

    private void saveDatabase(AzureConsumedServiceEnum serviceEnum, Long resourceId, Map<String, String> tagMap) {

        String tags = null;
        if (!MapUtils.isEmpty(tagMap)) {
            tags = JSONObject.toJSONString(tagMap);
        }
        switch (serviceEnum) {
            case STORAGEACCOUNT:
                StorageAccount storageAccount = storageAccountRepository.query(resourceId);
                storageAccount.setTags(tags);
                storageAccountRepository.update(storageAccount);
                break;
            case VM:
                CloudServer cloudServer = cloudServerRepository.query(resourceId);
//                cloudServer.setTags(tags);
                cloudServer.setCloudTags(tags);
                cloudServerRepository.update(cloudServer);
                break;
            case EIP:
                PublicIPAddress eip = publicIPAddressRepository.query(resourceId);
                eip.setTags(tags);
                publicIPAddressRepository.update(eip);
                break;
            case ROUTERTABLE:
                RouterTable routerTable = routerTableRepository.query(resourceId);
                routerTable.setTags(tags);
                routerTableRepository.update(routerTable);
                break;
            case VPC:
                Vpc vpc = vpcRepository.query(resourceId);
                vpc.setTags(tags);
                vpcRepository.update(vpc);
                break;
            case ASET:
                AvailabilitySet aset = availabilitySetRepository.query(resourceId);
                aset.setTags(tags);
                availabilitySetRepository.update(aset);
                break;
            case SNAPSHOT:
                Snapshot snapshot = snapshotRepository.query(resourceId);
                snapshot.setTags(tags);
                snapshotRepository.update(snapshot);
                break;
            case VOLUME:
                Volume volume = volumeRepository.query(resourceId);
                volume.setTags(tags);
                volumeRepository.update(volume);
                break;
            case SLB:
                Slb slb = slbRepository.query(resourceId);
                slb.setTags(tags);
                slbRepository.update(slb);
                break;
            case RESOURCEGROUP:
                ResourceGroup resourceGroup = resourceGroupRepository.query(resourceId);
                resourceGroup.setTags(tags);
                resourceGroupRepository.update(resourceGroup);
                break;
            case NICS:
                NetworkInterface nics = networkInterfaceRepository.query(resourceId);
                nics.setTags(tags);
                networkInterfaceRepository.update(nics);
                break;
            case SECURITYGROUP:
                SecurityGroup securityGroup = securityGroupRepository.query(resourceId);
                securityGroup.setTags(tags);
                securityGroupRepository.update(securityGroup);
                break;
            case MYSQL:
                AzureDatabaseServer mysql = mysqlRepository.query(resourceId);
                mysql.setTags(tags);
                mysqlRepository.update(mysql);
                break;
            case REDIS:
                CloudRedis redis = redisRepository.query(resourceId);
                redis.setTags(tags);
                redisRepository.update(redis);
                break;
            case KEYPAIR:
                Keypair keypair = keypairRepository.query(resourceId);
                keypair.setTags(tags);
                keypairRepository.update(keypair);
                break;
            case DDOS:
                DdosProtectionPlan ddosProtectionPlan = ddosProtectionPlanRepository.query(resourceId);
                ddosProtectionPlan.setTags(tags);
                ddosProtectionPlanRepository.update(ddosProtectionPlan);
                break;
            default:
                break;
        }
    }
}