package com.rj.config;

import com.rj.tenant.TenantContextHolder;
import com.rj.entity.sys.User;
import com.rj.service.sys.IUserService;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

/**
 * 多租户过滤器：
 * <p>
 * - 从 HTTP Header 中读取租户ID：X-Tenant-Id<br/>
 * - 将租户ID写入 {@link TenantContextHolder}<br/>
 * - 在请求结束时清理线程变量，避免线程复用造成的串租户问题
 * </p>
 */
@Component
@Order(Ordered.HIGHEST_PRECEDENCE + 10)
public class TenantFilter extends OncePerRequestFilter {

    private static final Logger log = LoggerFactory.getLogger(TenantFilter.class);

    /**
     * Header 名称常量，便于前后端约定与维护
     */
    public static final String TENANT_HEADER = "X-Tenant-Id";

    /**
     * 认证 Header 名，约定为 Bearer Token
     */
    public static final String AUTH_HEADER = "Authorization";

    private final IUserService userService;

    public TenantFilter(IUserService userService) {
        this.userService = userService;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {
        String headerTenantId = request.getHeader(TENANT_HEADER);
        String finalTenantId = null;

        // 1. 从 Authorization 头中解析 token，并查出用户的租户ID
        String authHeader = request.getHeader(AUTH_HEADER);
        String tokenTenantId = null;
        if (authHeader != null && !authHeader.isEmpty()) {
            String token = extractToken(authHeader);
            if (token != null && !token.isEmpty()) {
                User user = userService.getUserByToken(token);
                if (user != null) {
                    tokenTenantId = user.getTenantId();
                }
            }
        }

        try {
            // 2. 计算本次请求实际使用的租户ID，并校验一致性
            if (tokenTenantId != null && headerTenantId != null && !headerTenantId.isEmpty()
                    && !tokenTenantId.equals(headerTenantId)) {
                // Header 与 Token 中的租户不一致，记录告警日志（也可以按需直接拒绝请求）
                log.warn("Tenant mismatch between token and header. tokenTenantId={}, headerTenantId={}", tokenTenantId, headerTenantId);
            }

            if (tokenTenantId != null) {
                finalTenantId = tokenTenantId;
            } else if (headerTenantId != null && !headerTenantId.isEmpty()) {
                finalTenantId = headerTenantId;
            }

            // 设置租户上下文（允许为 null：如公共接口或未登录情况）
            TenantContextHolder.setTenantId(finalTenantId);

            filterChain.doFilter(request, response);
        } finally {
            // 无论请求是否成功，都要清理线程变量
            TenantContextHolder.clear();
        }
    }

    /**
     * 从 Authorization 头中提取实际的 token 值。
     * 支持形如 "Bearer xxx" 或直接传 token 的方式。
     */
    private String extractToken(String authHeader) {
        if (authHeader == null) {
            return null;
        }
        authHeader = authHeader.trim();
        if (authHeader.toLowerCase().startsWith("bearer ")) {
            return authHeader.substring(7).trim();
        }
        return authHeader;
    }
}



