package com.bocloud.ims.service.resource.fusionsphere;

import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.network.PortGroupDriver;
import com.bocloud.cmp.model.PortGroupModel;
import com.bocloud.common.model.*;
import com.bocloud.common.utils.MapTools;
import com.bocloud.ims.entity.resource.CloudVendor;
import com.bocloud.ims.entity.resource.PortGroup;
import com.bocloud.ims.entity.resource.Switcher;
import com.bocloud.ims.interfaces.resource.fusionsphere.FusionSpherePortGroupService;
import com.bocloud.ims.repository.resource.CloudVendorRepository;
import com.bocloud.ims.repository.resource.PortGroupRepository;
import com.bocloud.ims.repository.resource.SwitcherRepository;
import com.bocloud.ims.service.utils.ResourceEventPublisher;
import com.bocloud.service.lock.BocloudACLock;
import com.bocloud.service.lock.LockFactory;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
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 java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @Company: 博云 www.bocloud.com
 * @ClassName: FusionSpherePortGroupServiceImpl
 * @Description:
 * @author: zhenpingLi/李振平
 * @date: 2021/10/26 15:06
 */
@Slf4j
@Service
public class FusionSpherePortGroupServiceImpl implements FusionSpherePortGroupService {

    private static OperateResult.OperateCategory operateCategory = OperateResult.OperateCategory.ResourceEvent;
    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;
    @Autowired
    private ResourceEventPublisher resourceEventPublisher;
    @Autowired
    private LockFactory lockFactory;
    @Autowired
    private CloudVendorRepository vendorRepository;
    @Autowired
    private PortGroupRepository portGroupRepository;
    @Autowired
    private PortGroupDriver portGroupDriver;
    @Autowired
    private SwitcherRepository switcherRepository;

    @Override
    public BocloudResult<GridBean<PortGroup>> 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());
        Integer page = Optional.ofNullable(pager.getPage()).orElse(1);
        Integer rows = Optional.ofNullable(pager.getRows()).orElse(10);
        try {
            int total = portGroupRepository.count(params);
            List<PortGroup> list = this.portGroupRepository.list(page, rows, params, sorter);
            GridBean<PortGroup> gridBean = new GridBean<>(page, rows, total, list);
            return new BocloudResult<>(true, gridBean, "查询成功");
        } catch (Exception e) {
            log.error("list PortGroup error!", e);
            return new BocloudResult<>(false, "查询失败:" + e.getMessage());
        }
    }

    @Override
    public BocloudResult<PortGroup> detail(Long id, RequestContext context) {
        try {
            PortGroup entity = portGroupRepository.query(id);
            Assert.notNull(entity, "资源不存在");
            return new BocloudResult<>(true, entity, "查询详情成功");
        } catch (Exception e) {
            log.error("detail PortGroup fail:", e);
            return new BocloudResult<>(false, "查询详情失败:" + e.getMessage());
        }
    }

    @Override
    public BocloudResult<Void> create(PortGroup entityParams, RequestContext context) {
        try {
            CloudVendor vendor = vendorRepository.query(entityParams.getVendorId());
            Assert.notNull(vendor, "平台验证失败");
            Switcher switcher = switcherRepository.query(entityParams.getSwitcherId());
            Assert.notNull(switcher, "交换机不存在");
            if (portGroupRepository.exist(entityParams.getName(), entityParams.getSwitcherId())) {
                throw new RuntimeException("资源已存在");
            }
            PortGroupModel model = new PortGroupModel();
            BeanUtils.copyProperties(entityParams, model);
            model.setSwitcherUri(switcher.getUri());

            taskExecutor.execute(() -> {
                String operate = vendor.getType().toLowerCase() + ".portgroup";
                String message = "创建资源失败";
                BocloudResult result = portGroupDriver.create(vendor.getUuid(), null, model);
                try {
                    if (result.isSuccess()) {
                        message = "创建资源成功";
                        PortGroupModel newModel = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), PortGroupModel.class);
                        entityParams.setGroupVal(newModel.getGroupVal());
                        entityParams.setUri(newModel.getUri());
                        entityParams.setCreatorId(context.getTarget());
                        entityParams.setGmtCreate(new Date());
                        portGroupRepository.save(entityParams);
                    } else {
                        log.error("创建资源失败：" + result.getMessage());
                        message = result.getMessage();
                    }
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                } catch (Exception e) {
                    log.error("create resource fail:", e);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate, MapTools.simpleMap(
                            "vendorId", vendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult<>(true, "任务已下发，正在执行...");
        } catch (Exception e) {
            log.error("create resource error!", e);
            return new BocloudResult<>(false, "创建失败:" + e.getMessage());
        }
    }

    @Override
    public BocloudResult<Void> modify(PortGroup modifyParams, RequestContext context) {
        try {
            PortGroup entity = portGroupRepository.query(modifyParams.getId());
            Assert.notNull(entity, "数据不存在");
            CloudVendor vendor = vendorRepository.query(entity.getVendorId());
            Assert.notNull(vendor, "平台验证失败");

            PortGroupModel model = new PortGroupModel();
            model.setName(modifyParams.getName());
            model.setRemark(modifyParams.getRemark());
            model.setVlanId(modifyParams.getVlanId());
            model.setUri(entity.getUri());

            taskExecutor.execute(() -> {
                String operate = vendor.getType().toLowerCase() + ".portgroup";
                String message = "更新资源失败";
                BocloudResult result = portGroupDriver.modify(vendor.getUuid(), null, model);
                try {
                    if (result.isSuccess()) {
                        entity.setName(modifyParams.getName());
                        entity.setRemark(modifyParams.getRemark());
                        portGroupRepository.update(entity);
                        message = "更新资源成功";
                    } else {
                        log.error("更新资源失败：" + result.getMessage());
                        message = result.getMessage();
                    }
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                } catch (Exception e) {
                    log.error("modify resource fail:", e);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult<>(true, "任务已下发，正在执行...");
        } catch (Exception e) {
            log.error("modify resource error!", e);
            return new BocloudResult<>(false, "更新失败:" + e.getMessage());
        }
    }

    @Override
    public BocloudResult<Void> remove(Long id, RequestContext context) {
        String path = PortGroup.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            PortGroup entity = portGroupRepository.query(id);
            Assert.notNull(entity, "数据不存在");
            CloudVendor vendor = vendorRepository.query(entity.getVendorId());
            Assert.notNull(vendor, "平台验证失败");

            taskExecutor.execute(() -> {
                String operate = vendor.getType().toLowerCase() + ".portgroup";
                String message = "删除资源失败";
                BocloudResult result = portGroupDriver.remove(vendor.getUuid(), null, entity.getUri());
                try {
                    if (result.isSuccess()) {
                        message = "删除资源成功";
                        portGroupRepository.remove(id, context.getTarget());
                    } else {
                        log.error("删除资源失败：" + result.getMessage());
                        message = result.getMessage();
                    }
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                } catch (Exception e) {
                    log.error("remove resource fail:", e);
                    resourceEventPublisher.send(new OperateResult(result.isSuccess(), message, operate,
                            MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
                }
            });
            return new BocloudResult<>(true, "任务已下发，正在执行...");
        } catch (Exception e) {
            log.error("remove resource error!", e);
            return new BocloudResult<>(false, "删除失败:" + e.getMessage());
        }
    }
}