package com.jeequan.jeepay.core.interceptor;

import com.alibaba.fastjson.JSON;
import com.jeequan.jeepay.core.beans.RequestKitBean;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Component
public class ReqInfoInterceptor implements HandlerInterceptor {

    @Autowired
    private RequestKitBean requestKitBean;

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, @NonNull HttpServletResponse httpServletResponse, @NonNull Object handler) throws Exception {
        // 所有请求第一个进入的方法
        long startTime = System.currentTimeMillis();
        httpServletRequest.setAttribute("startTime", startTime);

        String contentType = httpServletRequest.getHeader(HttpHeaders.CONTENT_TYPE);

        Enumeration<String> headerNames = httpServletRequest.getHeaderNames();
        Map<String, Object> headers = new HashMap<>();

        while (headerNames.hasMoreElements()) {
            String key = headerNames.nextElement();
            String value = httpServletRequest.getHeader(key);
            headers.put(key, value);
        }

        if (handler instanceof HandlerMethod) {
            val h = ((HandlerMethod) handler);
            StringBuilder sb = new StringBuilder(1000);
            sb.append("------------------------------------------------------------\n");
            String typeName = h.getBean().getClass().getTypeName();
            typeName = typeName.replaceAll("(\\w)\\w*\\.", "$1.");
            int end = typeName.indexOf("$");
            if (end == -1) {
                end = typeName.length();
            }

            //部分请求链接
            sb.append("URI          : ").append(httpServletRequest.getRequestURI()).append("\n");
            //Controller 的包名
            sb.append("Controller   : ").append(typeName, 0, end).append("\n");
            //方法名称
            sb.append("Method       : ").append(h.getMethod().getName()).append("\n");
            // 请求头
            sb.append("headers      : ").append(JSON.toJSONString(headers)).append("\n");
            sb.append("Content-Type : ").append(contentType).append("\n");
            // 所有的请求参数, 表单或json
            sb.append("Params       : ").append(requestKitBean.getReqParamJSON()).append("\n");
            // body不在此处打印
            log.info("request info : \n {}", sb);
        }


        return true;
    }

    @Override
    public void postHandle(@NonNull HttpServletRequest httpServletRequest, @NonNull HttpServletResponse httpServletResponse, @NonNull Object o, ModelAndView modelAndView) {

    }

    @Override
    public void afterCompletion(@NonNull HttpServletRequest httpServletRequest, @NonNull HttpServletResponse httpServletResponse, @NonNull Object o, Exception e) {

    }

    private Map<String, Object> getParameterInfo(HttpServletRequest request) {
        Map<String, Object> parameter = new HashMap<>();
        Map<String, String[]> parameterMap = request.getParameterMap();

        for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
            String key = entry.getKey();
            String[] parameterValues = entry.getValue();
            if (parameterValues.length == 1) {
                int length = parameterValues[0].length();
                if (length > 255) {
                    parameter.put(key, parameterValues[0].substring(0, 255) + "...");
                } else {
                    parameter.put(key, parameterValues[0]);
                }
            } else {
                parameter.put(key, Arrays.toString(parameterValues));
            }
        }

        return parameter;
    }
}
