package com.xindazhou.framework.security.core.filter;

import com.auth0.jwt.interfaces.DecodedJWT;
import com.xindazhou.framework.common.pojo.CommonResult;
import com.xindazhou.framework.common.util.servlet.ServletUtils;
import com.xindazhou.framework.security.core.LoginUser;
import com.xindazhou.framework.security.core.jwt.ServiceJwtUtil;
import com.xindazhou.framework.security.core.util.SecurityFrameworkUtils;
import com.xindazhou.framework.web.core.handler.GlobalExceptionHandler;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

/**
 * 服务间调用的 JWT 认证过滤器
 * 验证来自其他服务的 JWT Token，并构建 LoginUser
 *
 * @author xindazhou
 */
@RequiredArgsConstructor
@Slf4j
public class ServiceJwtAuthenticationFilter extends OncePerRequestFilter {

    private static final String SERVICE_JWT_HEADER = "X-Service-JWT";

    private final GlobalExceptionHandler globalExceptionHandler;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        
        // 只处理 RPC API 请求
        String requestURI = request.getRequestURI();
        if (!requestURI.startsWith("/rpc-api/")) {
            chain.doFilter(request, response);
            return;
        }

        // 例外：OAuth2 token 相关接口不需要 JWT 验证
        // - /rpc-api/system/oauth2/token/create: 创建 token（登录时调用，还没有 token）
        // - /rpc-api/system/oauth2/token/refresh: 刷新 token（前端刷新时调用，可能没有服务间 JWT）
        // - /rpc-api/system/oauth2/token/check: 校验 token（网关验证时调用，可能没有服务间 JWT）
        // - /rpc-api/system/oauth2/token/remove: 删除 token（登出时调用，可能没有服务间 JWT）
        if (requestURI.equals("/rpc-api/system/oauth2/token/create") 
                || requestURI.equals("/rpc-api/system/oauth2/token/refresh")
                || requestURI.equals("/rpc-api/system/oauth2/token/check")
                || requestURI.equals("/rpc-api/system/oauth2/token/remove")) {
            chain.doFilter(request, response);
            return;
        }

        // 获取服务间 JWT Token
        String jwtToken = request.getHeader(SERVICE_JWT_HEADER);
        if (jwtToken == null || jwtToken.isEmpty()) {
            log.warn("[ServiceJwtAuthenticationFilter] RPC 请求缺少 JWT Token: {}", requestURI);
            CommonResult<?> result = CommonResult.error(401, "服务间调用缺少 JWT Token");
            ServletUtils.writeJSON(response, result);
            return;
        }

        try {
            // 验证 JWT Token
            DecodedJWT decodedJWT = ServiceJwtUtil.verifyToken(jwtToken);
            if (decodedJWT == null) {
                log.warn("[ServiceJwtAuthenticationFilter] JWT Token 验证失败: {}", requestURI);
                CommonResult<?> result = CommonResult.error(401, "JWT Token 验证失败");
                ServletUtils.writeJSON(response, result);
                return;
            }

            // 从 JWT 中提取用户信息
            Long userId = ServiceJwtUtil.getUserId(jwtToken);
            Integer userType = ServiceJwtUtil.getUserType(jwtToken);
            Long tenantId = ServiceJwtUtil.getTenantId(jwtToken);
            String serviceName = ServiceJwtUtil.getServiceName(jwtToken);

            // 构建 LoginUser
            LoginUser loginUser = new LoginUser();
            if (userId != null) {
                loginUser.setId(userId);
            }
            if (userType != null) {
                loginUser.setUserType(userType);
            }
            if (tenantId != null) {
                loginUser.setTenantId(tenantId);
            }
            // JWT 的 expiresAt 是 Date 类型，需要转换为 LocalDateTime
            if (decodedJWT.getExpiresAt() != null) {
                loginUser.setExpiresTime(java.time.LocalDateTime.ofInstant(
                        decodedJWT.getExpiresAt().toInstant(), 
                        java.time.ZoneId.systemDefault()));
            }

            // 设置到 SecurityContext
            SecurityFrameworkUtils.setLoginUser(loginUser, request);
            log.debug("[ServiceJwtAuthenticationFilter] 服务间 JWT 验证成功: service={}, userId={}, URL={}", 
                    serviceName, userId, requestURI);

        } catch (Exception ex) {
            log.error("[ServiceJwtAuthenticationFilter] JWT Token 验证异常: {}", requestURI, ex);
            CommonResult<?> result = globalExceptionHandler.allExceptionHandler(request, ex);
            ServletUtils.writeJSON(response, result);
            return;
        }

        // 继续过滤链
        chain.doFilter(request, response);
    }

}

