package cn.pluss.platform.interceptor;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
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.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * @author DJH
 */
@Slf4j
public class RequestInfoInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {
        // 所有请求第一个进入的方法
        String ip = httpServletRequest.getRemoteHost();
        InputStream is = httpServletRequest.getInputStream();
        StringBuilder responseStrBuilder = new StringBuilder();
        BufferedReader streamReader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
        String inputStr;
        while ((inputStr = streamReader.readLine()) != null) {
            responseStrBuilder.append(inputStr);
        }

        long startTime = System.currentTimeMillis();
        httpServletRequest.setAttribute("startTime", startTime);

        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) {
            StringBuilder sb = new StringBuilder(1000);
            String header = httpServletRequest.getHeader("user-agent");
            System.out.println("Header info : " + header);
            sb.append("------------------------------------------------------------\n");
            HandlerMethod h = (HandlerMethod) handler;
            String typeName = h.getBean().getClass().getTypeName();
            typeName = typeName.replaceAll("(\\w)\\w*\\.", "$1.");
            int end = typeName.indexOf("$");
            if (end == -1) {
                end = typeName.length();
            }

            //Controller 的包名
            sb.append("Controller: ").append(typeName, 0, end).append("\n");
            //方法名称
            sb.append("Method    : ").append(h.getMethod().getName()).append("\n");
            //所有的请求参数
            sb.append("Params    : ").append(getParameterInfo(httpServletRequest)).append("\n");

            if (responseStrBuilder.length() > 1000) {
                sb.append("body: ").append(responseStrBuilder.substring(0, 1000)).append("\n");
            } else {
                sb.append("body: ").append(responseStrBuilder).append("\n");
            }
            sb.append("headers   : ").append(JSONObject.toJSONString(headers)).append("\n");
            //部分请求链接
            sb.append("URI       : ").append(httpServletRequest.getRequestURI()).append("\n");

            log.info("request info : \n {}", sb);
        }


        return true;
    }

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

    }

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

    }

    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;
    }
}
