package com.bocloud.ims.service.resource;

import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.loadbalance.LbDriver;
import com.bocloud.cmp.entity.enums.CloudProvider;
import com.bocloud.cmp.model.LbListenerRuleModel;
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.common.utils.MapTools;
import com.bocloud.ims.entity.resource.CloudVendor;
import com.bocloud.ims.entity.resource.LbListener;
import com.bocloud.ims.entity.resource.LbListenerRule;
import com.bocloud.ims.entity.resource.LbPool;
import com.bocloud.ims.interfaces.resource.LbListenerRuleService;
import com.bocloud.ims.repository.resource.CloudVendorRepository;
import com.bocloud.ims.repository.resource.LbListenerRepository;
import com.bocloud.ims.repository.resource.LbListenerRuleRepository;
import com.bocloud.ims.repository.resource.LbPoolRepository;
import com.bocloud.ims.service.utils.ResourceEventPublisher;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import io.jsonwebtoken.lang.Assert;
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 java.util.*;

/**
 * @ClassName: LbListenerRuleServiceImpl
 * @Description:
 * @Author lxy
 * @Date 2021/10/19 16:15
 */
@Service("lbListenerRuleService")
public class LbListenerRuleServiceImpl implements LbListenerRuleService {
    private static Logger logger = LoggerFactory.getLogger(LbListenerRuleServiceImpl.class);
    @Autowired
    private LbDriver lbDriver;
    @Autowired
    private LbListenerRuleRepository lbListenerRuleRepository;
    @Autowired
    private LbListenerRepository lbListenerRepository;
    @Autowired
    private CloudVendorRepository cloudVendorRepository;
    @Autowired
    private LbPoolRepository lbPoolRepository;
    @Autowired
    private ResourceEventPublisher resourceEventPublisher;

    @Override
    public BocloudResult<GridBean<LbListenerRule>> list(Pager pager, RequestContext context) {
        GridBean gridBean = null;
        try {
            List<Param> params = Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>());
            Map<String, String> sorter = Optional.ofNullable(pager.getSorter()).orElse(Maps.newHashMap());
            Boolean simple = Optional.ofNullable(pager.getSimple()).orElse(false);
            Integer page = Optional.ofNullable(pager.getPage()).orElse(1);
            Integer rows = Optional.ofNullable(pager.getRows()).orElse(10);
            sorter.put("gmtCreate", Common.ONE);
            int total = lbListenerRuleRepository.count(params);
            if (simple) {
                if (0 == context.getTenant()) {
                    params.add(new Param(MapTools.simpleMap(Common.TENANTID, 0), Sign.EQ));
                }
                List<SimpleBean> beans = lbListenerRuleRepository.list(params, sorter);
                gridBean = new GridBean(1, 1, total, beans);
            } else {
                List<LbListenerRule> list = lbListenerRuleRepository.list(page, rows, params, sorter);
                gridBean = GridHelper.getBean(page, rows, total, list);
            }
            return new BocloudResult<>(true, gridBean, "查询成功");
        } catch (Exception e) {
            logger.error("list lb listener failure:", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    @Override
    public BocloudResult create(LbListenerRule listenerRule, RequestContext context) {
        BocloudResult result = new BocloudResult(false, "监听器转发创建失败");
        try {
            Long vendorId = listenerRule.getVendorId();
            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            if (null == vendor) {
                return new BocloudResult(false, "云平台不存在");
            }
            switch (CloudProvider.valueOf(vendor.getType())) {
                case VOLCENGINE:
                    result = createVOLCENGINE(listenerRule, context, vendor);
                    break;
                default:
                    result = new BocloudResult(false, "暂不支持此平台");
                    break;
            }

        } catch (Exception e) {
            logger.error("create ListenerRule fail:", e);
            result = new BocloudResult(false, "创建失败");
        }
        return result;
    }

    private BocloudResult createVOLCENGINE(LbListenerRule listenerRule, RequestContext context, CloudVendor vendor) {
        try {
            LbListener listener = lbListenerRepository.queryByUuid(listenerRule.getListenerUuid(), listenerRule.getVendorId());
            if (null == listener) {
                return new BocloudResult(false, "负载均衡器不存在");
            }
            LbPool lbPool = lbPoolRepository.queryByUuid(listenerRule.getPoolUuid(), listener.getVendorId());
            if (null == lbPool) {
                return new BocloudResult(false, "后端服务器组不存在");
            }
            LbListenerRuleModel model = new LbListenerRuleModel();
            BeanUtils.copyProperties(listenerRule, model);
            BocloudResult result = lbDriver.createListenerRule(vendor.getUuid(), lbPool.getRegionId(), model);
            if (result.isFailed()) {
                return result;
            }
            LbListenerRuleModel rule = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), LbListenerRuleModel.class);
            listenerRule.setRuleUuid(rule.getRuleUuid());
            listenerRule.setRegionId(rule.getRegionId());
            lbListenerRuleRepository.save(listenerRule);
            return new BocloudResult(true, listenerRule, "创建成功");
        } catch (Exception e) {
            logger.error("create listener rule fail:", e);
            return new BocloudResult(false, "创建失败");
        }
    }

    @Override
    public BocloudResult modify(LbListenerRule listenerRule, Long target) {
        BocloudResult result = new BocloudResult(false, "监听器转发创建失败");
        try {
            Long vendorId = listenerRule.getVendorId();
            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            if (null == vendor) {
                return new BocloudResult(false, "云平台不存在");
            }
            LbListenerRule rule = lbListenerRuleRepository.query(listenerRule.getId());
            if (null == rule) {
                return new BocloudResult(false, "负载均衡器转发策略不存在");
            }
            switch (CloudProvider.valueOf(vendor.getType())) {
                case VOLCENGINE:
                    LbListener listener = lbListenerRepository.queryByUuid(listenerRule.getListenerUuid(), listenerRule.getVendorId());
                    if (null == listener) {
                        return new BocloudResult(false, "负载均衡器不存在");
                    }
                    LbPool lbPool = lbPoolRepository.queryByUuid(listenerRule.getPoolUuid(), listenerRule.getVendorId());
                    if (null == lbPool) {
                        return new BocloudResult(false, "后端服务器组不存在");
                    }
                    if (listenerRule.getPoolUuid().equals(rule.getPoolUuid())) {
                        return new BocloudResult(false, "后端服务器组没做修改，请重新选择");
                    }
                    LbListenerRuleModel model = new LbListenerRuleModel();
                    rule.setPoolUuid(listenerRule.getPoolUuid());
                    BeanUtils.copyProperties(rule, model);
                    result = lbDriver.updateListenerRule(vendor.getUuid(), lbPool.getRegionId(), model);
                    if (result.isFailed()) {
                        return result;
                    }
                    rule.setGmtModify(new Date());
                    rule.setMenderId(target);
                    break;
                default:
                    result = new BocloudResult(false, "暂不支持此平台");
                    break;
            }
            lbListenerRuleRepository.update(rule);
            result = new BocloudResult(true, listenerRule, "修改成功");
        } catch (Exception e) {
            logger.error("update ListenerRule fail:", e);
            result = new BocloudResult(false, "修改失败");
        }
        return result;
    }

    @Override
    public BocloudResult<LbListenerRule> detail(Long id) {
        try {
            LbListenerRule rule = lbListenerRuleRepository.query(id);
            if (null == rule) {
                return new BocloudResult<>(false, "监听器转发规则不存在");
            }
            return new BocloudResult<>(true, rule, "查询成功");
        } catch (Exception e) {
            logger.error("query lb listener rule fail:", e);
            return new BocloudResult<>(false, "查询失败");
        }
    }

    @Override
    public BocloudResult remove(Long id, RequestContext context) {
        try {
            LbListenerRule rule = lbListenerRuleRepository.query(id);
            Assert.notNull(rule, "转发规则不存在");
            CloudVendor vendor = cloudVendorRepository.query(rule.getVendorId());
            Assert.notNull(vendor, "平台不存在");
            BocloudResult result = lbDriver.removeListenerRule(vendor.getUuid(), rule.getRegionId(), rule.getListenerUuid(), rule.getRuleUuid());
            lbListenerRuleRepository.remove(id, context.getTarget());
            return result;
        } catch (Exception e) {
            logger.error("remove lb listener rule fail:", e);
            return new BocloudResult<>(false, "删除失败");

        }
    }

    @Override
    public BocloudResult batchRemove(List<Long> idArray, RequestContext context) {
        if (ListTool.isEmpty(idArray)) {
            return new BocloudResult<>(false, "没有需要删除的监听器转发规则！");
        }
        try {
            List<BocloudResult> succList = Lists.newArrayList();
            List<BocloudResult> failList = Lists.newArrayList();
            Long vendorId = null;
            for (Long id : idArray) {
                LbListenerRule rule = lbListenerRuleRepository.query(id);
                if (null != rule) {
                    if (null == vendorId) {
                        vendorId = rule.getVendorId();
                    }
                    BocloudResult result = remove(id, context);
                    if (result.isSuccess()) {
                        succList.add(new BocloudResult<>(true, "【" + rule.getRuleUuid() + "】删除成功"));
                    } else {
                        failList.add(
                                new BocloudResult<>(false, "【" + rule.getRuleUuid() + "】删除失败：" + result.getMessage()));
                    }
                }
            }
            CloudVendor vendor = cloudVendorRepository.query(vendorId);
            String operate = vendor.getType().toLowerCase() + ".listener";
            // 删除成功的数量
            int success = succList.size();
            // 删除失败的数量
            int fail = failList.size();
            String content = null;
            if (fail == idArray.size()) {
                content = "监听器转发规则批量删除失败，详情如下：\n";
                for (BocloudResult bocloudResult : failList) {
                    content += bocloudResult.getMessage() + "\n";
                }
                resourceEventPublisher
                        .send(new OperateResult(false, content, operate, MapTools.simpleMap("vendorId", vendor.getId()),
                                OperateResult.OperateCategory.ResourceEvent, context));
            } else {
                content = "监听器转发规则批量删除成功【" + success + "】个,失败【" + fail + "】个，详情如下：\n";
                for (BocloudResult bocloudResult : succList) {
                    content += bocloudResult.getMessage() + "\n";
                }
                for (BocloudResult bocloudResult : failList) {
                    content += bocloudResult.getMessage() + "\n";
                }
                resourceEventPublisher
                        .send(new OperateResult(true, content, operate, MapTools.simpleMap("vendorId", vendor.getId()),
                                OperateResult.OperateCategory.ResourceEvent, context));
            }
        } catch (Exception e) {
            logger.error("batch remove load balancer fail:", e);
            return new BocloudResult<>(false, "批量删除任务下发失败");
        }
        return new BocloudResult<>(true, "批量删除任务已下发，正在执行...");
    }
}

