package tech.easyflow.publicapi.interceptor;

import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import tech.easyflow.common.domain.Result;
import tech.easyflow.common.util.ResponseUtil;
import tech.easyflow.common.web.error.RequestIdContext;
import tech.easyflow.publicapi.dto.PublicApiErrorDetail;
import tech.easyflow.system.entity.SysApiKey;
import tech.easyflow.system.service.SysApiKeyService;

import java.util.List;

/**
 * Public API 访问令牌与接口权限拦截器。
 */
@Component
public class PublicApiInterceptor implements HandlerInterceptor {

    /**
     * 请求中已完成认证的访问令牌属性名，供后续资源级鉴权复用。
     */
    public static final String AUTHENTICATED_API_KEY_ATTRIBUTE =
        PublicApiInterceptor.class.getName() + ".authenticatedApiKey";

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

    @Resource
    private SysApiKeyService sysApiKeyService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        String requestURI = request.getRequestURI();
        String apiKey = request.getHeader("ApiKey");

        if (apiKey == null || apiKey.isBlank()) {
            if (!isWorkflowApi(requestURI)) {
                Result<Void> failed = Result.fail(401, "密钥不正确");
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                ResponseUtil.renderJson(response, failed);
                return false;
            }
            Result<PublicApiErrorDetail> failed = Result.fail(
                    "缺少 ApiKey 请求头",
                    new PublicApiErrorDetail(
                            RequestIdContext.get(request),
                            "auth",
                            "ApiKey",
                            null,
                            List.of("有效的工作流 Public API Key"),
                            false));
            failed.setErrorCode(40101);
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            ResponseUtil.renderJson(response, failed);
            return false;
        }
        SysApiKey authenticatedApiKey =
            sysApiKeyService.checkApikeyPermission(apiKey, requestURI);
        request.setAttribute(
            AUTHENTICATED_API_KEY_ATTRIBUTE,
            authenticatedApiKey
        );
        return true;
    }

    /**
     * 判断是否为工作流公共 API，避免专项错误契约影响其他公共接口。
     *
     * @param requestUri 请求 URI
     * @return 是否为工作流公共 API
     */
    private boolean isWorkflowApi(String requestUri) {
        return requestUri != null
                && requestUri.contains("/public-api/workflow/");
    }
}
