package com.bocloud.ims.service.resource;

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

import org.apache.commons.lang3.StringUtils;
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 com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.network.RouteTableDriver;
import com.bocloud.cmp.entity.enums.CloudProvider;
import com.bocloud.cmp.model.RouteModel;
import com.bocloud.cmp.model.RouteTableModel;
import com.bocloud.common.model.*;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.GridHelper;
import com.bocloud.common.utils.ListTool;
import com.bocloud.ims.entity.resource.*;
import com.bocloud.ims.interfaces.resource.RouteTableService;
import com.bocloud.ims.repository.resource.*;
import com.bocloud.service.lock.BocloudACLock;
import com.bocloud.service.lock.LockFactory;
import com.google.common.collect.Maps;

@Service("routeTableService")
public class RouteTableServiceImpl implements RouteTableService {
    private static Logger logger = LoggerFactory.getLogger(RouteTableServiceImpl.class);
    @Autowired
    private RouteTableRepository routeTableRepository;
    @Autowired
    private RouteRepository routeRepository;
    @Autowired
    private RouteTableAssociationRepository associationRepository;
    @Autowired
    private CloudVendorRepository cloudVendorRepository;
    @Autowired
    private VpcRepository vpcRepository;
    @Autowired
    private RouteTableDriver routeTableDriver;
    @Autowired
    private LockFactory lockFactory;

    @Autowired
    private SubnetRepository subnetRepository;

    @Autowired
    private ResourceGroupRepository resourceGroupRepository;

    @Override
    public BocloudResult<GridBean<RouteTable>> list(Pager pager) {
        try {
            int page = pager.getPage();
            int rows = pager.getRows();
            List<Param> params = pager.getParams();
            Map<String, String> sorter = pager.getSorter();

            params = Optional.ofNullable(params).orElse(new ArrayList<>());
            sorter = Optional.ofNullable(sorter).orElse(Maps.newHashMap());
            sorter.put("gmtCreate", Common.ONE);
            int total = routeTableRepository.count(params);
            List<RouteTable> list = routeTableRepository.list(page, rows, params, sorter);
            for (RouteTable routeTable : list) {
                List uuids = new ArrayList();
                List<RouteTableAssociation> associations = associationRepository.listByVid(routeTable.getVendorId(),
                    routeTable.getRegionId(), routeTable.getId());
                for (RouteTableAssociation association : associations) {
                    if (association.getSubnetUuid() != null) {
                        uuids.add(association.getSubnetUuid());
                    }
                }
                routeTable.setSubnetAssociations(JSON.toJSONString(uuids).replace("\"", ""));

                // 获取交换机的uuid
                List<String> routeTableUuidList = subnetRepository.getUuidByRouteTableUuid(routeTable.getVendorId(),
                        routeTable.getRegionId(), routeTable.getUuid());
                routeTable.setSubnetUuids(routeTableUuidList);

                if (StringUtils.isNotBlank(routeTable.getResourceGroupUuid())) {
                    ResourceGroup resourceGroup =
                        resourceGroupRepository.getByUuid(routeTable.getResourceGroupUuid(), routeTable.getVendorId());
                    routeTable.setResourceGroupName(null != resourceGroup ? resourceGroup.getDisplayName() : "");
                }
                // 京东云关联子网个数
//                List<Subnet> subnets = subnetRepository.listByRouteId(routeTable.getId());
                // 腾讯云关联子网个数
                routeTable.setSubnetCount(routeTableUuidList.size());
            }
            GridBean gridBean = GridHelper.getBean(page, rows, total, list);
            return new BocloudResult<>(true, gridBean, "查询成功");
        } catch (Exception e) {
            logger.error("list route tables failure:", e);
            return new BocloudResult<>(false, "查询失败", null, null);
        }
    }

    @Override
    public BocloudResult<RouteTable> create(RouteTable routeTableParam, RequestContext context) {
        try {
            CloudVendor vendor = cloudVendorRepository.query(routeTableParam.getVendorId());
            if (null == vendor) {
                return new BocloudResult<>(false, "指定的地域下云平台不存在");
            }
            Vpc vpc = vpcRepository.query(routeTableParam.getVpcId());
            if (null == vpc) {
                return new BocloudResult<>(false, "VPC不存在");
            }
            RouteTableModel model = new RouteTableModel(routeTableParam.getName(), vpc.getVpcId());
            if (CloudProvider.JDCLOUD.name().equals(vendor.getType())) {
                model.setRemark(routeTableParam.getRemark());
            }
            BocloudResult result = routeTableDriver.create(model, vendor.getUuid(), routeTableParam.getRegionId());
            if (result.isFailed()) {
                return new BocloudResult<>(false, "创建失败:" + result.getMessage(), null, null);
            }
            RouteTable routeTable = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), RouteTable.class);
            if (!CloudProvider.JDCLOUD.name().equals(vendor.getType())) {
                routeTable.setPropagatingVgws("[]");
            }
            routeTable.setVendorId(vendor.getId());
            routeTable.setCreatorId(context.getTarget());
            routeTable.setVpcId(vpc.getId());
            routeTable.setRegionId(vpc.getRegionId());
            routeTableRepository.save(routeTable);

            RouteTableModel routeTableModel = (RouteTableModel)result.getData();
            if (!ListTool.isEmpty(routeTableModel.getRouteModels())) {
                for (RouteModel routeModel : routeTableModel.getRouteModels()) {
                    Route route = new Route();
                    BeanUtils.copyProperties(routeModel, route);
                    route.setRouteTableId(routeTable.getId());
                    route.setRouteTableUuid(routeTable.getUuid());
                    route.setCreatorId(context.getTarget());
                    route.setGmtCreate(new Date());
                    route.setVendorId(vendor.getId());
                    route.setRegionId(vpc.getRegionId());
                    routeRepository.save(route);
                }
            }
            return new BocloudResult<RouteTable>(true, routeTable, "创建成功");
        } catch (Exception e) {
            logger.error("create route table failure:", e);
            return new BocloudResult<RouteTable>(false, "创建失败", null, null);
        }
    }

    @Override
    public BocloudResult<String> remove(Long id, RequestContext context) {
        try {
            RouteTable routeTable = routeTableRepository.query(id);
            if (routeTable == null) {
                return new BocloudResult<>(false, "路由表不存在", null, null);
            }
            CloudVendor vendor = cloudVendorRepository.query(routeTable.getVendorId());
            if (null == vendor) {
                return new BocloudResult<>(false, "指定的地域下云平台不存在");
            }
            if (CloudProvider.JDCLOUD.name().equals(vendor.getType())) {
                List<Subnet> subnets = subnetRepository.listByRouteId(id);
                if (subnets.size() > 0) {
                    return new BocloudResult<>(false, "无法删除，请先解关子网");
                }
            }
            BocloudResult result =
                routeTableDriver.delete(routeTable.getUuid(), vendor.getUuid(), routeTable.getRegionId());
            if (result.isFailed()) {
                return new BocloudResult<>(false, "删除失败:" + result.getMessage(), null, null);
            }
            routeTableRepository.remove(routeTable.getId(), context.getTarget());
            // 删除路由条目
            routeRepository.removeByRouteTable(vendor.getId(), context.getTarget(), routeTable.getRegionId(),
                routeTable.getUuid());
            return new BocloudResult<>(true, "删除成功");
        } catch (Exception e) {
            logger.error("delete route table failure:", e);
            return new BocloudResult<>(false, "删除失败", null, null);
        }
    }

    @Override
    public BocloudResult<RouteTable> modify(RouteTable routeTableParam, RequestContext context) {
        RouteTable route = routeTableParam;
        String path = RouteTable.class.getSimpleName() + "_" + route.getId();
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            RouteTable oldRoutetable = routeTableRepository.query(route.getId());
            Assert.notNull(oldRoutetable, "RouteTable不存在!");
            CloudVendor cloudVendor = cloudVendorRepository.query(oldRoutetable.getVendorId());
            Assert.notNull(cloudVendor, "云平台不存在!");
            RouteTableModel model = JSONObject.parseObject(JSONObject.toJSONString(route), RouteTableModel.class);
            model.setUuid(oldRoutetable.getUuid());
            BocloudResult bocloudResult =
                routeTableDriver.update(model, cloudVendor.getUuid(), oldRoutetable.getRegionId());
            if (bocloudResult.isFailed()) {
                return bocloudResult;
            }
            BeanUtils.copyProperties(model, oldRoutetable);
            oldRoutetable.setMenderId(context.getTarget());
            routeTableRepository.update(oldRoutetable);
            return new BocloudResult<RouteTable>(true, oldRoutetable, "修改成功");
        } catch (Exception e) {
            logger.error("Modify route table fail:", e);
            return new BocloudResult<RouteTable>(false, "修改失败", null, null);
        }
    }

    @Override
    public BocloudResult<RouteTable> detail(Long id) {
        try {
            RouteTable routeTable = routeTableRepository.query(id);
            if (null == routeTable) {
                return new BocloudResult<>(false, "路由表不存在");
            }
            List uuids = new ArrayList();
            List<RouteTableAssociation> associations =
                associationRepository.listByVid(routeTable.getVendorId(), routeTable.getRegionId(), routeTable.getId());
            for (RouteTableAssociation association : associations) {
                if (association.getSubnetUuid() != null) {
                    uuids.add(association.getSubnetUuid());
                }
            }
            routeTable.setSubnetAssociations(JSON.toJSONString(uuids).replace("\"", ""));
            return new BocloudResult<>(true, routeTable, "查询成功");
        } catch (Exception e) {
            logger.error("query route table fail:", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    @Override
    public BocloudResult<List<RouteTable>> listNotAttachBySubnet(Long subnetId) {
        try {
            Subnet query = subnetRepository.query(subnetId);
            if (query == null) {
                return new BocloudResult<>(false, "该子网不存在");
            }
            List<RouteTable> routeTables = routeTableRepository.listNotAttachBySubnet(subnetId, query.getVpcId());
            return new BocloudResult<>(true, routeTables, "查询成功");
        } catch (Exception e) {
            logger.error("query route table fail:", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }
}
