package cn.axzo.workflow.server.common.filter;

import cn.azxo.framework.common.constatns.Constants;
import com.google.common.base.Strings;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.apm.toolkit.trace.Trace;
import org.apache.skywalking.apm.toolkit.trace.TraceContext;
import org.slf4j.MDC;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.UUID;

/**
 * Http接口日志记录
 *
 * @author wangli
 * @since 2024/2/19 16:23
 */
@Slf4j
@Component
public class HttpTraceLogFilter extends OncePerRequestFilter implements Ordered {
    private static final String X_REQUEST_ID = "x-request-id";

    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }

    @Override
    @Trace(operationName = "HttpTraceLogFilter")
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {
        String requestId = request.getHeader(X_REQUEST_ID);
        if (Strings.isNullOrEmpty(requestId)) {
            MDC.put(X_REQUEST_ID, getTraceId());
        } else {
            MDC.put(X_REQUEST_ID, requestId);
        }
        String ctxLogId = request.getHeader(Constants.CTX_LOG_ID_MDC);
        if (Strings.isNullOrEmpty(ctxLogId)) {
            MDC.put(Constants.CTX_LOG_ID_MDC, getTraceId());
        } else {
            MDC.put(Constants.CTX_LOG_ID_MDC, ctxLogId);
        }

        try {
            filterChain.doFilter(request, response);
        } finally {
            response.setHeader(Constants.CTX_LOG_ID_MDC, MDC.get(Constants.CTX_LOG_ID_MDC));
            response.setHeader(X_REQUEST_ID, MDC.get(Constants.CTX_LOG_ID_MDC));
            MDC.clear();
        }
    }

    private String getTraceId() {
        String contextTraceId = TraceContext.traceId();
        return Strings.isNullOrEmpty(contextTraceId)
                ? UUID.randomUUID().toString().replaceAll("-", "") : contextTraceId;
    }
}
