package com.ruoyi.web.modules.industryservice.research.filter;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.http.MediaType;
import org.springframework.web.filter.OncePerRequestFilter;
import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.web.modules.industryservice.research.config.ResearchOpenApiProperties;
import com.ruoyi.web.modules.industryservice.research.support.ResearchOpenApiConstants;
import com.ruoyi.web.modules.industryservice.research.support.ResearchOpenApiSupport;
import com.ruoyi.web.modules.industryservice.research.support.ResearchOpenApiTokenService;

/**
 * 科研开放数据接口 Token 鉴权（除 {@code /auth/token} 外均需 Bearer Token）。
 */
public class ResearchOpenApiAuthFilter extends OncePerRequestFilter
{
    private final ResearchOpenApiProperties properties;

    private final ResearchOpenApiTokenService tokenService;

    public ResearchOpenApiAuthFilter(ResearchOpenApiProperties properties,
            ResearchOpenApiTokenService tokenService)
    {
        this.properties = properties;
        this.tokenService = tokenService;
    }

    @Override
    protected boolean shouldNotFilter(HttpServletRequest request)
    {
        String uri = request.getRequestURI();
        if (uri == null || !uri.startsWith(ResearchOpenApiConstants.API_PREFIX))
        {
            return true;
        }
        return uri.startsWith(ResearchOpenApiConstants.AUTH_TOKEN_PATH);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException
    {
        if (!properties.isEnabled())
        {
            writeJson(response, HttpServletResponse.SC_SERVICE_UNAVAILABLE,
                    ResearchOpenApiSupport.error(503, "科研开放接口未启用"));
            return;
        }
        String token = resolveBearerToken(request);
        if (StringUtils.isEmpty(token))
        {
            writeJson(response, HttpServletResponse.SC_UNAUTHORIZED,
                    ResearchOpenApiSupport.error(401, "缺少 Authorization Bearer Token"));
            return;
        }
        try
        {
            tokenService.validateToken(token);
            chain.doFilter(request, response);
        }
        catch (Exception ex)
        {
            writeJson(response, HttpServletResponse.SC_UNAUTHORIZED,
                    ResearchOpenApiSupport.error(401, ex.getMessage()));
        }
    }

    static String resolveBearerToken(HttpServletRequest request)
    {
        String header = request.getHeader(ResearchOpenApiConstants.HEADER_AUTHORIZATION);
        if (StringUtils.isEmpty(header))
        {
            return null;
        }
        if (header.startsWith(ResearchOpenApiConstants.BEARER_PREFIX))
        {
            return header.substring(ResearchOpenApiConstants.BEARER_PREFIX.length()).trim();
        }
        return header.trim();
    }

    private static void writeJson(HttpServletResponse response, int status, Object body) throws IOException
    {
        response.setStatus(status);
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.getWriter().write(JSON.toJSONString(body));
    }
}
