package com.sf.service.gateway.service.impl;

import java.util.*;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONException;
import com.sf.common.utils.DateUtils;
import com.sf.common.utils.SecurityUtils;
import com.sf.common.utils.URLUtils;
import com.sf.service.gateway.domain.GatewayRoute;
import com.sf.service.gateway.domain.GatewayServer;
import com.sf.service.gateway.domain.dto.InsertOrUpdateGatewayRouteDTO;
import com.sf.service.gateway.enums.*;
import com.sf.service.gateway.mapper.GatewayRouteMapper;
import com.sf.service.gateway.service.IGatewayRouteService;
import com.sf.service.gateway.service.IGatewayServerService;
import com.sf.service.index.util.AppUtils;
import org.hibernate.validator.constraints.URL;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.validation.constraints.NotBlank;

/**
 * 路由管理Service业务层处理
 * 
 * @author 邹坤
 * @date 2024-04-22
 */
@Service
public class GatewayRouteServiceImpl implements IGatewayRouteService
{
    @Autowired
    private GatewayRouteMapper gatewayRouteMapper;

    @Autowired
    private IGatewayServerService gatewayServerService;

    /**
     * 查询路由管理
     * 
     * @param id 路由管理主键
     * @return 路由管理
     */
    @Override
    public GatewayRoute selectGatewayRouteById(Long id)
    {
        return gatewayRouteMapper.selectGatewayRouteById(id);
    }

    /**
     * 查询路由管理列表
     * 
     * @param gatewayRoute 路由管理
     * @return 路由管理
     */
    @Override
    public List<GatewayRoute> selectGatewayRouteList(GatewayRoute gatewayRoute)
    {
        return gatewayRouteMapper.selectGatewayRouteList(gatewayRoute);
    }

    /**
     * 新增路由管理
     * 
     * @param dto 路由管理
     * @return 结果
     */
    @Override
    public int insertGatewayRoute(InsertOrUpdateGatewayRouteDTO dto)
    {
        checkRouteConfig(dto);
        GatewayRoute gatewayRoute = new GatewayRoute();
        gatewayRoute.setRouteName(dto.getRouteName());
        gatewayRoute.setRequestProtocol(dto.getRequestProtocol().getCode());
        gatewayRoute.setRouteType(dto.getRouteType().getCode());
        gatewayRoute.setRouteContent(JSON.toJSONString(dto.getRouteContent()));
        gatewayRoute.setRouteStatusActiveMonitoring(dto.getRouteStatusActiveMonitoring());
        gatewayRoute.setRouteActiveMonitoringPath(dto.getRouteActiveMonitoringPath());
        gatewayRoute.setRouteActiveMonitoringTimeout(dto.getRouteActiveMonitoringTimeout());
        gatewayRoute.setAppCode(AppUtils.getAppCodeFromRequestHeader());
        String username = SecurityUtils.getUsername();
        gatewayRoute.setCreated(username);
        gatewayRoute.setModified(username);
        Date nowDate = DateUtils.getNowDate();
        gatewayRoute.setCreateTime(nowDate);
        gatewayRoute.setUpdateTime(nowDate);
        gatewayRoute.setRouteActiveStatus(GatewayDataStatus.ENABLE.getCode().equals(dto.getRouteStatusActiveMonitoring())?
                RouteActiveStatus.OBTAINING.getCode()
                :RouteActiveStatus.NOT_ENABLED.getCode());
        try {
            return gatewayRouteMapper.insertGatewayRoute(gatewayRoute);
        }catch (DuplicateKeyException e){
            throw new IllegalArgumentException("路由名称不可重复!");
        }
    }

    private void checkRouteConfig(InsertOrUpdateGatewayRouteDTO dto) {
        RequestProtocol requestProtocol = dto.getRequestProtocol();
        GatewayRouteType routeType = dto.getRouteType();
        Assert.notNull(requestProtocol,"不支持的协议类型！");
        Assert.notNull(routeType,"不支持的路由类型！");
        List<GatewayRoute.RouteContent> contentList = dto.getRouteContent();
        int sumWeight = 0;
        for (GatewayRoute.RouteContent content : contentList) {
            Assert.isTrue(URLUtils.isURL(content.getServerAddress()),"请输入正确的服务地址");
            switch (routeType){
                case WEIGHT_ROUTE:
                    if (content.getWeight() == null){
                        content.setWeight(0);
                    }
                    sumWeight += content.getWeight();
                    break;
                case HEADER_ROUTE:
                    Assert.notBlank(content.getHeaderKey(),"请求头键值不能为空");
                    MatchType matchType = MatchType.getByCode(content.getMatchType());
                    Assert.notNull(matchType,"匹配方式不能为空");
                    break;
                default:
                    break;
            }
        }
        if (GatewayRouteType.WEIGHT_ROUTE.equals(routeType)){
            Assert.isTrue(sumWeight == 100,"权重总值为100！");
        }
        if (GatewayDataStatus.ENABLE.getCode().equals(dto.getRouteStatusActiveMonitoring())){
            Long routeActiveMonitoringTimeout = dto.getRouteActiveMonitoringTimeout();
            Assert.notNull(routeActiveMonitoringTimeout,"路由探活超时时间不能为空");
            Assert.isTrue(0 <= routeActiveMonitoringTimeout && routeActiveMonitoringTimeout <= 30000,"路由探活超时时间在0-30000之间！");
        }
    }

    /**
     * 修改路由管理
     * 
     * @param dto 路由管理
     * @return 结果
     */
    @Override
    public int updateGatewayRoute(InsertOrUpdateGatewayRouteDTO dto)
    {
        checkRouteConfig(dto);
        GatewayRoute gatewayRoute = new GatewayRoute();
        gatewayRoute.setId(dto.getId());
        gatewayRoute.setRouteName(dto.getRouteName());
        gatewayRoute.setRequestProtocol(dto.getRequestProtocol().getCode());
        gatewayRoute.setRouteType(dto.getRouteType().getCode());
        gatewayRoute.setRouteContent(JSON.toJSONString(dto.getRouteContent()));
        gatewayRoute.setRouteStatusActiveMonitoring(dto.getRouteStatusActiveMonitoring());
        gatewayRoute.setRouteActiveMonitoringPath(dto.getRouteActiveMonitoringPath());
        gatewayRoute.setRouteActiveMonitoringTimeout(dto.getRouteActiveMonitoringTimeout());
        gatewayRoute.setModified(SecurityUtils.getUsername());
        gatewayRoute.setUpdateTime(DateUtils.getNowDate());
        if (GatewayDataStatus.DISABLE.getCode().equals(dto.getRouteStatusActiveMonitoring())){
            gatewayRoute.setRouteActiveStatus(RouteActiveStatus.NOT_ENABLED.getCode());
        }
        try {
            return gatewayRouteMapper.updateGatewayRoute(gatewayRoute);
        }catch (DuplicateKeyException e){
            throw new IllegalArgumentException("路由名称不可重复!");
        }
    }

    /**
     * 批量删除路由管理
     * 
     * @param ids 需要删除的路由管理主键
     * @return 结果
     */
    @Override
    public int deleteGatewayRouteByIds(Long[] ids)
    {
        checkDeleteConditions(CollUtil.newHashSet(ids));
        return gatewayRouteMapper.deleteGatewayRouteByIds(ids);
    }

    /**
     * 删除路由管理信息
     * 
     * @param id 路由管理主键
     * @return 结果
     */
    @Override
    public int deleteGatewayRouteById(Long id)
    {
        checkDeleteConditions(Collections.singleton(id));
        return gatewayRouteMapper.deleteGatewayRouteById(id);
    }

    private void checkDeleteConditions(Collection<Long> ids) {
        List<GatewayServer> serverList = gatewayServerService.selectGatewayServerByRouteIds(ids);
        Assert.isTrue(CollUtil.isEmpty(serverList),"存在关联服务，删除失败！");
    }

    @Override
    public List<GatewayRoute> selectGatewayRouteByIds(Collection<Long> ids) {
        if (CollectionUtils.isEmpty(ids)){
            return Collections.emptyList();
        }
        return gatewayRouteMapper.selectGatewayRouteByIds(ids);
    }
}
