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

import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import apijson.JSON;
import cn.hutool.core.collection.CollUtil;
import com.sf.common.utils.DateUtils;
import com.sf.service.gateway.domain.GatewayInterfaceLinkStrategy;
import com.sf.service.gateway.domain.GatewayServer;
import com.sf.service.gateway.domain.GatewayStrategy;
import com.sf.service.gateway.enums.GatewayDataStatus;
import com.sf.service.gateway.enums.GatewayStrategyType;
import com.sf.service.gateway.mapper.GatewayInterfaceLinkStrategyMapper;
import com.sf.service.gateway.mapper.GatewayStrategyMapper;
import com.sf.service.gateway.service.IGatewayStrategyService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

/**
 * 策略管理Service业务层处理
 * 
 * @author zoukun
 * @date 2024-04-22
 */
@Slf4j
@Service
public class GatewayStrategyServiceImpl implements IGatewayStrategyService
{
    @Autowired
    private GatewayStrategyMapper gatewayStrategyMapper;

    @Autowired
    private GatewayInterfaceLinkStrategyMapper gatewayInterfaceLinkStrategyMapper;

    /**
     * 查询策略管理
     *
     * @param id 策略管理主键
     * @return 策略管理
     */
    @Override
    public GatewayStrategy selectGatewayStrategyById(Long id)
    {
        return gatewayStrategyMapper.selectGatewayStrategyById(id);
    }

    /**
     * 查询策略管理列表
     * 
     * @param gatewayStrategy 策略管理
     * @return 策略管理
     */
    @Override
    public List<GatewayStrategy> selectGatewayStrategyList(GatewayStrategy gatewayStrategy)
    {
        return gatewayStrategyMapper.selectGatewayStrategyList(gatewayStrategy);
    }

    /**
     * 新增策略管理
     * 
     * @param gatewayStrategy 策略管理
     * @return 结果
     */
    @Override
    public int insertGatewayStrategy(GatewayStrategy gatewayStrategy)
    {
        Date nowDate = DateUtils.getNowDate();
        gatewayStrategy.setCreateTime(nowDate);
        gatewayStrategy.setUpdateTime(nowDate);
        GatewayStrategyType strategyType = GatewayStrategyType.getByCode(gatewayStrategy.getStrategyType());
        Assert.notNull(strategyType,"不支持的策略类型！");
        switch (strategyType){
            case AUTHENTICATION:
                checkAuthenticationConfig(gatewayStrategy);
                break;
            case PERMISSION:
                checkPermissionConfig(gatewayStrategy);
                break;
            case CURRENT_LIMITING:
                checkAndInitCurrentLimitingConfig(gatewayStrategy);
                break;
            case CIRCUIT_BREAKER:
                checkAndInitCircuitBreakerConfig(gatewayStrategy);
                break;
            default:
                break;
        }
        try {
            return gatewayStrategyMapper.insertGatewayStrategy(gatewayStrategy);
        }catch (DuplicateKeyException e){
            throw new IllegalArgumentException("策略名称不可重复!");
        }

    }

    /**
     * 认证策略配置检查
     *
     * @param gatewayStrategy
     */
    private void checkAuthenticationConfig(GatewayStrategy gatewayStrategy) {
    }

    /**
     * 鉴权策略配置检查
     *
     * @param gatewayStrategy
     */
    private void checkPermissionConfig(GatewayStrategy gatewayStrategy) {
    }

    /**
     * 限流策略配置检查
     *
     * @param gatewayStrategy
     */
    private void checkAndInitCurrentLimitingConfig(GatewayStrategy gatewayStrategy) {
        Integer currentLimitingThreshold = gatewayStrategy.getCurrentLimitingThreshold();
        Integer currentLimitingTimeWindow = gatewayStrategy.getCurrentLimitingTimeWindow();
        String currentLimitingResponse = gatewayStrategy.getCurrentLimitingResponse();
        Assert.notNull(currentLimitingThreshold,"限流值不能为空");
        Assert.isTrue(currentLimitingThreshold >= 0,"限流值>=0");
        // 页面没有,这里给个默认值
        if (currentLimitingTimeWindow == null) {
            gatewayStrategy.setCurrentLimitingTimeWindow(1);
        }else {
            Assert.isTrue(currentLimitingTimeWindow >= 0,"限流窗口值>=0");
        }
        Assert.isTrue(JSON.isJSONObject(currentLimitingResponse),"请输入正确的JSON格式限流响应信息");
    }

    /**
     * 熔断策略配置检查
     *
     * @param gatewayStrategy
     */
    private void checkAndInitCircuitBreakerConfig(GatewayStrategy gatewayStrategy) {
        Integer circuitBreakerThreshold = gatewayStrategy.getCircuitBreakerThreshold();
        Integer circuitBreakerTimeWindow = gatewayStrategy.getCircuitBreakerTimeWindow();
        Integer circuitBreakerRecoveryInterval = gatewayStrategy.getCircuitBreakerRecoveryInterval();
        String circuitBreakerResponse = gatewayStrategy.getCircuitBreakerResponse();
        Assert.notNull(circuitBreakerThreshold,"接口调用失败阈值不能为空");
        Assert.isTrue(circuitBreakerThreshold >= 0,"限流值>=0");
        Assert.notNull(circuitBreakerTimeWindow,"调用失败阈值对应的单位时间不能为空");
        Assert.isTrue(circuitBreakerTimeWindow >= 0,"调用失败阈值对应的单位时间>=0");
        Assert.notNull(circuitBreakerRecoveryInterval,"熔断后恢复的时间间隔不能为空");
        Assert.isTrue(circuitBreakerRecoveryInterval >= 0,"熔断后恢复的时间间隔>=0");
        Assert.isTrue(JSON.isJSONObject(circuitBreakerResponse),"请输入正确的JSON格式熔断响应信息");
    }

    /**
     * 修改策略管理
     * 
     * @param gatewayStrategy 策略管理
     * @return 结果
     */
    @Override
    public int updateGatewayStrategy(GatewayStrategy gatewayStrategy)
    {
        gatewayStrategy.setUpdateTime(DateUtils.getNowDate());
        try {
            return gatewayStrategyMapper.updateGatewayStrategy(gatewayStrategy);
        }catch (DuplicateKeyException e){
            throw new IllegalArgumentException("策略名称不可重复!");
        }
    }

    /**
     * 批量删除策略管理
     * 
     * @param ids 需要删除的策略管理主键
     * @return 结果
     */
    @Override
    public int deleteGatewayStrategyByIds(Long[] ids)
    {
        if (ids == null || ids.length == 0) {
            return 0;
        }
        checkDeleteConditions(CollUtil.newHashSet(ids));
        return gatewayStrategyMapper.deleteGatewayStrategyByIds(ids);
    }

    /**
     * 删除策略管理信息
     * 
     * @param id 策略管理主键
     * @return 结果
     */
    @Override
    public int deleteGatewayStrategyById(Long id)
    {
        if (id == null) {
            return 0;
        }
        checkDeleteConditions(Collections.singleton(id));
        return gatewayStrategyMapper.deleteGatewayStrategyById(id);
    }

    private void checkDeleteConditions(Collection<Long> ids) {
        List<GatewayInterfaceLinkStrategy> linkList = gatewayInterfaceLinkStrategyMapper.selectGatewayInterfaceLinkStrategyByStrategyIds(ids);
        Assert.isTrue(CollUtil.isEmpty(linkList),"策略已关联接口，删除失败");}

    @Override
    public int updateGatewayStrategyStatusByIds(List<Long> ids, GatewayDataStatus status) {
        if (CollectionUtils.isEmpty(ids) || status == null){
            log.warn("Insufficient update conditions");
            return 0;
        }
        return gatewayStrategyMapper.updateGatewayStrategyStatusByIds(ids,status.getCode());
    }

    @Override
    public List<GatewayStrategy> selectGatewayStrategyByIds(Collection<Long> ids) {
        if (CollectionUtils.isEmpty(ids)){
            return Collections.emptyList();
        }
        return gatewayStrategyMapper.selectGatewayStrategyByIds(ids);
    }
}
