package cn.myapps.conf;

import cn.myapps.authtime.common.dao.PersistenceUtils;
import com.auth0.jwt.exceptions.JWTDecodeException;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.util.ContentCachingRequestWrapper;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;

public class CommonsExceptionResolver implements HandlerExceptionResolver {

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

    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o,
                                         Exception e) {
        String url = httpServletRequest.getRequestURI();
        try {
            PersistenceUtils.closeSessionAndConnection();
            boolean unAuthorized = e instanceof JWTDecodeException;
            if(!unAuthorized) {
                try {
                    if (httpServletRequest instanceof ContentCachingRequestWrapper) {
                        ContentCachingRequestWrapper rqw = (ContentCachingRequestWrapper) httpServletRequest;
                        String body = new String(rqw.getContentAsByteArray(), StandardCharsets.UTF_8);
                        StringBuilder sbHeader = new StringBuilder();
                        Enumeration<String> pNames = rqw.getParameterNames();
                        if (pNames != null) {
                            while (pNames.hasMoreElements()) {
                                String pName = pNames.nextElement();
                                sbHeader.append(String.format("%s=%s", pName, rqw.getParameter(pName)));
                            }
                        }

                        log.error("请求发生异常:{}", String.format("param=%s;body=%s", sbHeader, body), e);
                    } else {
                        log.error("请求发生异常:{}", url, e);
                    }
                } catch (Exception ex) {
                    log.error("resolveException记录参数异常:{}={}", url, ex.toString(), e);
                }
            }

            /**
             * 响应被提交之前, 不允许更改响应状态
             */
            if(!httpServletResponse.isCommitted()) {
                httpServletResponse.setContentType("text/json;charset=utf-8");
                httpServletResponse.resetBuffer();
                try (PrintWriter writer = httpServletResponse.getWriter()) {
                    JSONObject json = new JSONObject();
                    String message = "系统异常, 请联系管理员";
                    if (unAuthorized) {
                        httpServletResponse.setStatus(401);
                        message = "未授权操作";
                    } else {
                        httpServletResponse.setStatus(500);
                    }

                    json.put("errcode", httpServletResponse.getStatus());
                    json.put("errmsg", message);
                    json.put("detail", e.toString());

                    writer.print(json);
                }

                httpServletResponse.flushBuffer();
            }
        } catch (Exception ex) {
            log.error("执行发生异常:{}-{}", url, ex, e);
        }

        return null;
    }
}
