package cn.meowrain.aioj.backend.gateway.filter;

import cn.meowrain.aioj.backend.framework.core.errorcode.ErrorCode;
import cn.meowrain.aioj.backend.framework.core.exception.RemoteException;
import cn.meowrain.aioj.backend.framework.core.web.Result;
import cn.meowrain.aioj.backend.framework.core.web.Results;
import cn.meowrain.aioj.backend.gateway.config.GatewayPropertiesConfiguration;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
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.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.Objects;

@Slf4j
@Component
@RequiredArgsConstructor
public class AuthGlobalFilter implements GlobalFilter, Ordered {

	private final WebClient.Builder webClientBuilder;

	@Autowired
	private GatewayPropertiesConfiguration gatewayPropertiesConfiguration;

	private final AntPathMatcher antPathMatcher = new AntPathMatcher();

	private final ObjectMapper objectMapper = new ObjectMapper();


	@Override
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
		ServerHttpRequest request = exchange.getRequest();
		String path = request.getURI().getPath();

		log.info("🚀 网关拦截请求: {}", path);
		log.debug("📋 白名单配置: {}", gatewayPropertiesConfiguration.getWhiteList());

		// 检查是否在白名单中
		if (isWhiteListPath(path)) {
			log.info("✅ 路径 {} 在白名单中，跳过认证", path);
			return chain.filter(exchange);
		}

		// 获取Authorization头
		String authHeader = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
		if (authHeader == null || !authHeader.startsWith("Bearer ")) {
			log.warn("⚠️ 请求缺少有效的 Authorization 头: {}", path);
			return handleUnauthorized(exchange);
		}

		String token = authHeader.substring(7);

		// 调用auth服务验证token
		return validateToken(token)
			.flatMap(isValid -> {
				if (isValid) {
					log.info("🔓 Token 验证成功: {}", path);
					return chain.filter(exchange);
				} else {
					log.warn("🔒 Token 验证失败: {}", path);
					return handleUnauthorized(exchange);
				}
			})
			.onErrorResume(throwable -> {
				log.error("❌ Token 验证异常: {}", path, throwable);
				return handleUnauthorized(exchange);
			});
	}

	/**
	 * 检查路径是否在白名单中
	 */
	private boolean isWhiteListPath(String path) {
		// 检查配置文件中的白名单
		if (gatewayPropertiesConfiguration.getWhiteList() != null && !gatewayPropertiesConfiguration.getWhiteList().isEmpty()) {
			for (String whitePath : gatewayPropertiesConfiguration.getWhiteList()) {
				if (antPathMatcher.match(whitePath, path)) {
					return true;
				}
			}
		}

		return false;
	}

	/**
	 * 调用auth服务验证token
	 */
	private Mono<Boolean> validateToken(String token) {
		return webClientBuilder.build()
			.post()
			.uri("lb://aioj-auth-service/api/v1/auth/validate")
			.header(HttpHeaders.AUTHORIZATION, "Bearer " + token)
			.contentType(MediaType.APPLICATION_JSON)
			.retrieve()
			.bodyToMono(String.class)
			.map(response -> {
				try {
					// 解析响应，判断是否有效
					Result result = objectMapper.readValue(response, Result.class);
					return Objects.equals(result.getData(), true);
				} catch (JsonProcessingException e) {
					log.error("❌ 解析认证服务响应失败", e);
					return false;
				}
			})
			.defaultIfEmpty(false);
	}

	/**
	 * 处理未授权的请求
	 */
	private Mono<Void> handleUnauthorized(ServerWebExchange exchange) {
		ServerHttpResponse response = exchange.getResponse();
		response.setStatusCode(HttpStatus.UNAUTHORIZED);
		response.getHeaders().setContentType(MediaType.APPLICATION_JSON);

		Result<Void> result = Results.failure(new RemoteException(ErrorCode.NO_AUTH_ERROR));
		String responseBody;
		try {
			responseBody = objectMapper.writeValueAsString(result);
		} catch (JsonProcessingException e) {
			responseBody = "{\"code\":401,\"message\":\"Unauthorized\",\"data\":null}";
		}

		DataBuffer buffer = response.bufferFactory().wrap(responseBody.getBytes(StandardCharsets.UTF_8));
		return response.writeWith(Mono.just(buffer));
	}

	@Override
	public int getOrder() {
		// 设置较高的优先级，确保在其他过滤器之前执行
		return -100;
	}

}
