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

import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.azure.network.RouterTableDriver;
import com.bocloud.cmp.driver.network.SubnetDriver;
import com.bocloud.cmp.model.SubnetModel;
import com.bocloud.cmp.model.azure.network.RouterTableModel;
import com.bocloud.cmp.params.azure.RouterTableOperationParams;
import com.bocloud.common.model.*;
import com.bocloud.common.utils.Common;
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.BatchAccount;
import com.bocloud.ims.entity.resource.azure.network.RouterTable;
import com.bocloud.ims.interfaces.resource.azure.network.RouterTableService;
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.network.RouterTableRepository;
import com.bocloud.service.lock.BocloudACLock;
import com.bocloud.service.lock.LockFactory;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;

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

/**
 * @Company: 博云 www.bocloud.com
 * @ClassName: RouterTableServiceImpl
 * @Description:
 * @author: zhenpingLi/李振平
 * @date: 2021/1/5 10:12
 */
@Service("routerTableService")
public class RouterTableServiceImpl implements RouterTableService {

    private static Logger logger = LoggerFactory.getLogger(RouterTableServiceImpl.class);
    @Autowired
    private CloudVendorRepository vendorRepository;
    @Autowired
    private LockFactory lockFactory;
    @Autowired
    private ResourceGroupRepository resourceGroupRepository;
    @Autowired
    private RouterTableRepository routerTableRepository;
    @Autowired
    private RouterTableDriver routerTableDriver;
    @Autowired
    private SubnetRepository subnetRepository;
    @Autowired
    private SubnetDriver subnetDriver;
    @Autowired
    private VpcRepository vpcRepository;

    @Override
    public BocloudResult<GridBean<RouterTable>> 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 {
            int total = routerTableRepository.count(params);
            List<RouterTable> list = this.routerTableRepository.list(page, rows, params, sorter);
            GridBean<RouterTable> gridBean = new GridBean<>(page, rows, total, list);
            return new BocloudResult<>(true, gridBean, "查询成功");
        } catch (Exception e) {
            logger.error("list routerTable error!", e);
            return new BocloudResult<>(false, "查询失败:" + e.getMessage());
        }
    }

    @Override
    public BocloudResult<Void> create(RouterTable entityParams, RequestContext context) {
        try {
            CloudVendor vendor = vendorRepository.query(entityParams.getVendorId());
            if (ObjectUtils.isEmpty(vendor)) {
                logger.error("get cloudVendor failure");
                return new BocloudResult<>(false, "平台验证失败");
            }
            if (null != routerTableRepository.getByName(entityParams.getVendorId(), entityParams.getResourceGroupId(), entityParams.getName())) {
                return new BocloudResult<>(false, "名称已存在");
            }
            ResourceGroup resourceGroup = resourceGroupRepository.query(entityParams.getResourceGroupId());
            if (ObjectUtils.isEmpty(resourceGroup)) {
                logger.error("get resourceGroup failure");
                return new BocloudResult<>(false, "资源组不能为空");
            }
            RouterTableModel model = new RouterTableModel();
            BeanUtils.copyProperties(entityParams, model);
            model.setResourceGroupName(resourceGroup.getName());
            BocloudResult result = routerTableDriver.create(vendor.getUuid(), entityParams.getRegionId(), model);
            if (result.isFailed()) {
                return new BocloudResult<>(false, result.getMessage());
            }
            model = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), RouterTableModel.class);
            BeanUtils.copyProperties(model, entityParams);
            entityParams.setCreatorId(context.getTarget());
            entityParams.setGmtCreate(new Date());
            entityParams.setProjectId(context.getProject());
            entityParams.setTenantId(context.getTenant());
            routerTableRepository.save(entityParams);
            return new BocloudResult<>(true, "创建成功");
        } catch (Exception e) {
            logger.error("create routerTable error!", e);
            return new BocloudResult<>(false, "创建失败:" + e.getMessage());
        }
    }

    @Override
    public BocloudResult<Void> remove(Long id, RequestContext context) {
        String path = BatchAccount.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            RouterTable entity = routerTableRepository.query(id);
            if (null == entity) {
                logger.error("The data doesn't exist");
                return new BocloudResult<>(false, "数据不存在");
            }
            CloudVendor vendor = vendorRepository.query(entity.getVendorId());
            if (null == vendor) {
                logger.error("get cloudVendor failure");
                return new BocloudResult<>(false, "平台验证失败");
            }
            BocloudResult result = routerTableDriver.remove(vendor.getUuid(), entity.getRegionId(), entity.getUuid());
            if (result.isFailed()) {
                return new BocloudResult<>(false, result.getMessage());
            }
            routerTableRepository.remove(id, context.getTarget());
            return new BocloudResult<>(true, "删除成功");
        } catch (Exception e) {
            logger.error("remove routerTable error!", e);
            return new BocloudResult<>(false, "删除失败:" + e.getMessage());
        }
    }

    @Override
    public BocloudResult<RouterTable> detail(Long id, RequestContext context) {
        try {
            RouterTable entity = routerTableRepository.query(id);
            return new BocloudResult<>(true, entity, "查询详情成功");
        } catch (Exception e) {
            logger.error("query routerTable error!", e);
            return new BocloudResult<>(false, "查询详情失败:" + e.getMessage());
        }
    }

    @Override
    public BocloudResult<List<Subnet>> unbindSubnet(Long id, RequestContext context) {
        try {
            RouterTable routerTable = routerTableRepository.query(id);
            if (ObjectUtils.isEmpty(routerTable)) {
                logger.error("get routerTable failure");
                return new BocloudResult<>(false, "数据不存在");
            }
            ResourceGroup resourceGroup = resourceGroupRepository.query(routerTable.getResourceGroupId());
            if (ObjectUtils.isEmpty(resourceGroup)) {
                logger.error("get resourceGroup failure");
                return new BocloudResult<>(false, "资源组不能为空");
            }

            List<Vpc> vpcs = vpcRepository.listByRsg(routerTable.getVendorId(), routerTable.getRegionId(), context.getTenant(), resourceGroup.getName());
            List<Subnet> collect = new ArrayList<>();
            for (Vpc vpc : vpcs) {
                List<Subnet> subnets = subnetRepository.listByNetwork(vpc.getId());
                collect = subnets.stream().filter(subnet -> subnet.getRouterTableId() == null).collect(Collectors.toList());
            }
            return new BocloudResult<>(true, collect, "查询成功");
        } catch (Exception e) {
            logger.error("query subnet error!", e);
            return new BocloudResult<>(false, "查询失败:" + e.getMessage());
        }
    }

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

    public BocloudResult<Void> associate(RouterTableOperationParams params, RequestContext context) {
        try {
            RouterTable routerTable = routerTableRepository.query(params.getId());
            if (ObjectUtils.isEmpty(routerTable)) {
                logger.error("get routerTable failure");
                return new BocloudResult<>(false, "数据不存在");
            }
            CloudVendor vendor = vendorRepository.query(routerTable.getVendorId());
            if (ObjectUtils.isEmpty(vendor)) {
                logger.error("get cloudVendor failure");
                return new BocloudResult<>(false, "平台验证失败");
            }
            Subnet subnet = subnetRepository.query(params.getSubnetId());
            if (ObjectUtils.isEmpty(subnet)) {
                logger.error("get sunbnet failure");
                return new BocloudResult<>(false, "数据不存在");
            }
            SubnetModel model = new SubnetModel();
            model.setVpcUuid(subnet.getVpcUuid());
            model.setName(subnet.getName());
            model.setRouterTableUuid(routerTable.getUuid());
            BocloudResult result = subnetDriver.associate(vendor.getUuid(), routerTable.getRegionId(), model);
            if (result.isFailed()) {
                return new BocloudResult<>(false, result.getMessage());
            }
            subnet.setRouterTableId(params.getId());
            subnet.setMenderId(context.getTarget());
            subnet.setGmtModify(new Date());
            subnetRepository.update(subnet);
            return new BocloudResult<>(true, "关联成功");
        } catch (Exception e) {
            logger.error("associate subnet error!", e);
            return new BocloudResult<>(false, "关联失败:" + e.getMessage());
        }
    }

    public BocloudResult<Void> release(RouterTableOperationParams params, RequestContext context) {
        try {
            Subnet subnet = subnetRepository.query(params.getSubnetId());
            if (ObjectUtils.isEmpty(subnet)) {
                logger.error("get sunbnet failure");
                return new BocloudResult<>(false, "数据不存在");
            }
            CloudVendor vendor = vendorRepository.query(subnet.getVendorId());
            if (ObjectUtils.isEmpty(vendor)) {
                logger.error("get cloudVendor failure");
                return new BocloudResult<>(false, "平台验证失败");
            }
            SubnetModel model = new SubnetModel();
            model.setVpcUuid(subnet.getVpcUuid());
            model.setName(subnet.getName());
            BocloudResult result = subnetDriver.release(vendor.getUuid(), subnet.getRegionId(), model);
            if (result.isFailed()) {
                return new BocloudResult<>(false, result.getMessage());
            }
            subnet.setRouterTableId(null);
            subnet.setMenderId(context.getTarget());
            subnet.setGmtModify(new Date());
            subnetRepository.update(subnet);
            return new BocloudResult<>(true, "解绑成功");
        } catch (Exception e) {
            logger.error("release subnet error!", e);
            return new BocloudResult<>(false, "解绑失败:" + e.getMessage());
        }
    }

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


}