package com.mosty.base.gateway.filter;

import com.mosty.common.redis.service.RedisService;
import com.mosty.common.token.JWTUtil;
import com.mosty.common.token.UserInfo;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
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.GeoOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Date;

import static com.mosty.base.gateway.filter.FilterOrderConstant.TOKEN_FILTER_ORDER;

@Slf4j
@AllArgsConstructor
public class JwtFilter implements GlobalFilter, Ordered {

    private final RedisService redisService;
    private final RedisTemplate redisTemplate;
    private static final String TOKEN_PREFIX = "token:";

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");
        if (token == null || token.isEmpty()) {
            log.info("token is empty...");
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        UserInfo userInfo = JWTUtil.getUserInfo(token);
        if (userInfo == null) {
            log.error("get token exception");
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        String tokenKey = TOKEN_PREFIX + userInfo.getDeptId() + ":" + userInfo.getUserId();
        Long time = (Long) redisTemplate.opsForValue().get(tokenKey);
        if (time == null) {
            redisTemplate.delete(tokenKey);
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        Date date = new Date(time);
        int second = getMinutes(new Date(), date);
        if (second > 30) {
            log.error("token 过期");
            redisTemplate.delete(tokenKey);
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        if (second > 5) {
            redisTemplate.opsForValue().set(tokenKey, System.currentTimeMillis());
        }
        return chain.filter(exchange);
    }

    /**
     * 获取两个时间相差的分钟数
     *
     * @param date1 后面时间
     * @param date2 前面时间
     * @return 相差分支树
     */
    public static int getMinutes(Date date1, Date date2) {
        int minutes = 0;
        if (null != date1 && null != date2) {
            minutes = (int) ((date1.getTime() - date2.getTime()) / (60 * 1000));
        }
        return minutes;
    }

    @Override
    public int getOrder() {
        return TOKEN_FILTER_ORDER;
    }
}
