package com.qiuguo.iot.gateway.filter;

import com.qiuguo.iot.base.constans.RedisConstans;
import com.qiuguo.iot.base.constans.UserAuthContains;
import com.qiuguo.iot.gateway.config.properties.XssProperties;
import java.time.Duration;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
import org.springframework.http.server.RequestPath;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * XXX
 *
 * @author weiyachao
 * @since 2023/9/21 17:56
 */
@Component
@Slf4j
public class AuthFilter implements GlobalFilter, Ordered {
    
    @Autowired
    private ReactiveStringRedisTemplate reactiveRedisTemplate;
    
    @Autowired
    private XssProperties xssProperties;
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String url = request.getPath().toString();
        if (xssProperties.getExcludeUrls().contains(url)) {
            return chain.filter(exchange);
        }

        String api_token = exchange.getRequest().getHeaders().getFirst(UserAuthContains.API_TOKEN);
        String api_type = exchange.getRequest().getHeaders().getFirst(UserAuthContains.API_TYPE);
        if (ObjectUtils.isEmpty(api_token) || ObjectUtils.isEmpty(api_type)) {
            return Mono.error(new RuntimeException("未登录"));
        }
        String key = RedisConstans.IOT_TOKEN.concat(api_token);
        return reactiveRedisTemplate.getExpire(key).map(Duration::getSeconds).flatMap(ttl -> {
            if (ttl == -1) {
                // 用户没登陆
                return Mono.error(new RuntimeException("未登录"));
            } else if (ttl <= 3600) {
                // token 将要失效
                return reactiveRedisTemplate.expire(key, Duration.ofDays(7)).then(chain.filter(exchange));
            } else {
                // 正常登录
                return chain.filter(exchange);
            }
        });
    }
    
    
    @Override
    public int getOrder() {
        return -1;
    }
}
