package com.tofly.toflygateway.balance;

import com.tofly.common.core.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.gateway.config.LoadBalancerProperties;
import org.springframework.cloud.gateway.filter.LoadBalancerClientFilter;
import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.server.ServerWebExchange;

import java.net.URI;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR;


@Slf4j
public class ToflyLoadBalancerClientFilter extends LoadBalancerClientFilter {

    @Autowired
    private ToflyFilterConfig toflyFilterConfig;
    @Autowired
    private StringRedisTemplate redisTemplate;

    public ToflyLoadBalancerClientFilter(LoadBalancerClient loadBalancer, LoadBalancerProperties properties) {
        super(loadBalancer, properties);
    }

    @Override
    protected ServiceInstance choose(ServerWebExchange exchange) {
        if (this.loadBalancer instanceof RibbonLoadBalancerClient) {
            RibbonLoadBalancerClient client = (RibbonLoadBalancerClient) this.loadBalancer;
            String serviceId = ((URI) exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR)).getHost();
            if (!serviceId.equalsIgnoreCase("tofly-auth")) {
                String token = exchange.getRequest().getHeaders().getFirst("Authorization");

                log.info("从Authorization获取到的token为:{}", token);

                String access_token = exchange.getRequest().getQueryParams().getFirst("access_token");
                token = StringUtil.isEmpty(token) ? access_token : token;

                if (!StringUtil.isEmpty(token)) {
                    token = token.replace("bearer ", "");

                    URI uri = exchange.getRequest().getURI();
                    String path = uri.getPath();
                    boolean matches = checkFiltersUrl(serviceId, path);

                    // 返回false就要做token续签，true不续签
                    if (!matches) {
                        String redisTokenKey = "tofly_oauth:auth:" + token;
                        Boolean aBoolean = redisTemplate.hasKey(redisTokenKey);
                        if (null != aBoolean && aBoolean) {
                            Long expire = redisTemplate.getExpire(redisTokenKey);
                            if (null != expire && expire != -2) {
                                log.info("当前用户为token设置失效时长为：{},续签时长为：：" + toflyFilterConfig.getTokenExpireTime(), expire);
                                //设置token时间，续签时间配置
                                redisTemplate.expire(redisTokenKey, toflyFilterConfig.getTokenExpireTime(), TimeUnit.SECONDS);
                            }
                        }
                    }

                    return client.choose(serviceId, token);
                }
            }
        }
        return super.choose(exchange);
    }


    protected boolean checkFiltersUrl(String serviceId, String path) {
        boolean flag = false;
        List<String> listBase = toflyFilterConfig.getBaseUrl();
        List<String> listScada = toflyFilterConfig.getScadaUrl();
        List<String> listGps = toflyFilterConfig.getGpsUrl();
        List<String> listGis = toflyFilterConfig.getGisUrl();
        List<String> listMis = toflyFilterConfig.getMisUrl();
        switch (serviceId.toLowerCase()) {
            case "tofly-base":
                if (listBase != null) {
                    flag = listBase.contains(path);
                }
                break;
            case "tofly-scada":
                if (listScada != null) {
                    flag = listScada.contains(path);
                }
                break;
            case "tofly-xrtymis":
                if (listMis != null) {
                    flag = listMis.contains(path);
                }
                break;
            case "tofly-xrtygis":
                if (listGis != null) {
                    flag = listGis.contains(path);
                }
                break;
            case "tofly-xrty-gps":
                if (listGps != null) {
                    flag = listGps.contains(path);
                }
                break;
            default:
                break;
        }
        return flag;

    }

}
