package com.lingyue.gateway.filter;

import com.lingyue.common.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Arrays;
import java.util.List;

/**
 * JWT 认证过滤器
 */
@Slf4j
@Component
public class JwtAuthenticationFilter implements GlobalFilter, Ordered {
    
    /**
     * JWT 密钥（从配置读取）
     */
    @Value("${jwt.secret:lingyue-zhibao-secret-key-2024-please-change-in-production}")
    private String jwtSecret;
    
    /**
     * 不需要认证的路径
     */
    private static final List<String> EXCLUDED_PATHS = Arrays.asList(
        "/api/v1/auth/register",
        "/api/v1/auth/login",
        "/api/v1/auth/refresh"
    );
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getURI().getPath();
        
        // 检查是否为不需要认证的路径
        if (isExcludedPath(path)) {
            return chain.filter(exchange);
        }
        
        // 从请求头获取Token
        String token = getTokenFromRequest(request);
        
        if (!StringUtils.hasText(token)) {
            log.warn("Missing token for path: {}", path);
            return unauthorizedResponse(exchange);
        }
        
        // 验证Token
        if (!JwtUtil.validateToken(token, jwtSecret)) {
            log.warn("Invalid token for path: {}", path);
            return unauthorizedResponse(exchange);
        }
        
        // 从Token中获取用户ID并添加到请求头
        String userId = JwtUtil.getUserIdFromToken(token, jwtSecret);
        if (userId != null) {
            ServerHttpRequest modifiedRequest = request.mutate()
                .header("X-User-Id", userId)
                .build();
            exchange = exchange.mutate().request(modifiedRequest).build();
        }
        
        return chain.filter(exchange);
    }
    
    /**
     * 检查是否为不需要认证的路径
     */
    private boolean isExcludedPath(String path) {
        return EXCLUDED_PATHS.stream().anyMatch(path::startsWith);
    }
    
    /**
     * 从请求头获取Token
     */
    private String getTokenFromRequest(ServerHttpRequest request) {
        String bearerToken = request.getHeaders().getFirst("Authorization");
        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);
        }
        return null;
    }
    
    /**
     * 返回未授权响应
     */
    private Mono<Void> unauthorizedResponse(ServerWebExchange exchange) {
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        return response.setComplete();
    }
    
    @Override
    public int getOrder() {
        return -100;
    }
}

