package com.dora.config;

import com.dora.entity.User;
import com.dora.service.ApiKeyService;
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.lang.NonNull;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.Collections;

/**
 * API Key认证过滤器
 * 
 * <p>支持用户通过HTTP Header传入API Key进行认证，实现无需JWT的API调用。
 * 这使得普通用户（非会员）也可以通过API Key + 积分的方式使用AI服务。
 * 
 * <p>认证方式：
 * <ul>
 *   <li>Header名称：Authorization</li>
 *   <li>格式：Bearer {apiKey}</li>
 *   <li>示例：Authorization: Bearer ak_1234567890abcdef1234567890abcdef</li>
 * </ul>
 * 
 * <p>优先级：
 * <ol>
 *   <li>如果已通过JWT认证，跳过API Key认证</li>
 *   <li>如果存在API Key，尝试使用API Key认证</li>
 *   <li>如果两者都没有，继续到下一个过滤器</li>
 * </ol>
 * 
 * @author 1818AI
 * @since 2025-10-20
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class ApiKeyAuthenticationFilter extends OncePerRequestFilter {

    private final ApiKeyService apiKeyService;

    @Override
    protected void doFilterInternal(
            @NonNull HttpServletRequest request,
            @NonNull HttpServletResponse response,
            @NonNull FilterChain filterChain) throws ServletException, IOException {

        // 如果用户已经通过JWT认证，跳过API Key认证
        if (SecurityContextHolder.getContext().getAuthentication() != null &&
            SecurityContextHolder.getContext().getAuthentication().isAuthenticated() &&
            !"anonymousUser".equals(SecurityContextHolder.getContext().getAuthentication().getName())) {
            
            log.debug("用户已通过JWT认证，跳过API Key认证");
            filterChain.doFilter(request, response);
            return;
        }

        // 从请求头获取Authorization
        String authorizationHeader = request.getHeader("Authorization");
        if (authorizationHeader == null || authorizationHeader.trim().isEmpty()) {
            log.debug("未提供Authorization头，继续到下一个过滤器");
            filterChain.doFilter(request, response);
            return;
        }

        // 检查是否以"Bearer "开头
        if (!authorizationHeader.startsWith("Bearer ")) {
            log.debug("Authorization头格式不正确（非Bearer格式），继续到下一个过滤器");
            filterChain.doFilter(request, response);
            return;
        }

        // 提取API Key
        String apiKey = authorizationHeader.substring(7).trim();
        if (apiKey.isEmpty()) {
            log.warn("Authorization头中的API Key为空");
            filterChain.doFilter(request, response);
            return;
        }

        // 验证API Key（不再检查会员限制，支持所有用户）
        try {
            User user = apiKeyService.validateApiKeyForNonMember(apiKey);
            if (user == null) {
                log.warn("无效的API Key: {}", maskApiKey(apiKey));
                filterChain.doFilter(request, response);
                return;
            }

            // API Key验证成功，设置认证上下文
            UsernamePasswordAuthenticationToken authentication = 
                UsernamePasswordAuthenticationToken.authenticated(
                    user.getId().toString(),
                    null,
                    Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER"))
                );
            
            SecurityContextHolder.getContext().setAuthentication(authentication);
            log.info("用户 {} 通过API Key认证成功", user.getId());

        } catch (Exception e) {
            log.error("API Key认证过程中发生错误: {}", e.getMessage());
        }

        filterChain.doFilter(request, response);
    }

    /**
     * API Key脱敏处理
     */
    private String maskApiKey(String apiKey) {
        if (apiKey == null || apiKey.length() < 8) {
            return "****";
        }
        return apiKey.substring(0, 4) + "****" + apiKey.substring(apiKey.length() - 4);
    }
}

