package com.bocloud.ims.service.resource;

import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.network.RouteDriver;
import com.bocloud.cmp.entity.enums.CloudProvider;
import com.bocloud.cmp.model.RouteModel;
import com.bocloud.common.model.*;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.GridHelper;
import com.bocloud.ims.entity.resource.CloudVendor;
import com.bocloud.ims.entity.resource.Route;
import com.bocloud.ims.entity.resource.RouteTable;
import com.bocloud.ims.interfaces.resource.RouteService;
import com.bocloud.ims.repository.resource.CloudVendorRepository;
import com.bocloud.ims.repository.resource.RouteRepository;
import com.bocloud.ims.repository.resource.RouteTableRepository;
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 java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

@Service("routeService")
public class RouteServiceImpl implements RouteService {
    private static Logger logger = LoggerFactory.getLogger(RouteServiceImpl.class);
    @Autowired
    private RouteRepository routeRepository;
    @Autowired
    private RouteTableRepository routeTableRepository;
    @Autowired
    private CloudVendorRepository cloudVendorRepository;
    @Autowired
    private RouteDriver routeDriver;
    @Autowired
    private LockFactory lockFactory;

    @Override
    public BocloudResult<GridBean<Route>> list(Pager pager) {
        try {
            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);
            Integer page = Optional.ofNullable(pager.getPage()).orElse(1);
            Integer rows = Optional.ofNullable(pager.getRows()).orElse(10);

            int total = routeRepository.count(params);
            List<Route> list = routeRepository.list(page, rows, params, sorter);
            GridBean<Route> gridBean = GridHelper.getBean(page, rows, total, list);
            return new BocloudResult<GridBean<Route>>(true, gridBean, "查询成功");
        } catch (Exception e) {
            logger.error("list routes failure:", e);
            return new BocloudResult<GridBean<Route>>(false, "查询失败", null, null);
        }
    }

    @Override
    public BocloudResult<Route> create(Route route, RequestContext context) {
        try {
            CloudVendor vendor = cloudVendorRepository.query(route.getVendorId());
            Assert.notNull(vendor, "云平台不存在");
            RouteTable routeTable = routeTableRepository.query(route.getRouteTableId());
            Assert.notNull(routeTable, "RouteTable不存在");
            route.setRouteTableUuid(routeTable.getUuid());
            RouteModel model = new RouteModel();
            BeanUtils.copyProperties(route, model);
            BocloudResult result = routeDriver.create(model, vendor.getUuid(), route.getRegionId());
            if (result.isFailed()) {
                return new BocloudResult<Route>(false, "创建失败:" + result.getMessage(), null, null);
            }
            if (CloudProvider.ALIYUN.name().equals(vendor.getType())) {
                route.setType("Custom");// 自定义路由
                // uuid
                if (null != result.getData()) {
                    JSONObject parseObject = JSONObject.parseObject(JSONObject.toJSONString(result.getData()),
                            JSONObject.class);
                    route.setUuid(parseObject.getString("routeEntryId"));
                }
            }
            if (CloudProvider.VOLCENGINE.name().equals(vendor.getType())) {
                route.setType("Custom");// 自定义路由
                // uuid
                if (null != result.getData()) {
                    JSONObject parseObject = JSONObject.parseObject(JSONObject.toJSONString(result.getData()),
                            JSONObject.class);
                    route.setUuid(parseObject.getString("uuid"));
                }
            }
            route.setOrigin("CreateRoute");
            route.setState("Available");
            route.setVendorId(vendor.getId());
            route.setCreatorId(context.getTarget());
            route.setRegionId(route.getRegionId());
            routeRepository.save(route);
            return new BocloudResult<Route>(true, route, "创建成功");
        } catch (Exception e) {
            logger.error("create route failure:", e);
            return new BocloudResult<Route>(false, "创建失败:" + e.getMessage());
        }
    }

    @Override
    public BocloudResult<String> remove(Long id, RequestContext context) {
        try {
            Route route = routeRepository.query(id);
            if (route == null) {
                return new BocloudResult<>(false, "路由表不存在", null, null);
            }
            CloudVendor vendor = cloudVendorRepository.query(route.getVendorId());
            if (null == vendor) {
                return new BocloudResult<>(false, "指定的地域下云平台不存在");
            }
            RouteModel model = new RouteModel();
            BeanUtils.copyProperties(route, model);
            BocloudResult result = routeDriver.delete(model, vendor.getUuid(), route.getRegionId());
            if (result.isFailed()) {
                return new BocloudResult<>(false, "删除失败:" + result.getMessage(), null, null);
            }
            routeRepository.remove(route.getId(), context.getTarget());
            return new BocloudResult<>(true, "删除成功");
        } catch (Exception e) {
            logger.error("delete route failure:", e);
            return new BocloudResult<>(false, "删除失败", null, null);
        }
    }

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