package com.yxcheng.token.common.exception.handler;


import com.alibaba.fastjson.JSONObject;
import com.yxcheng.token.common.enumutil.AcceptErrorEnum;
import com.yxcheng.token.common.enumutil.ResultEnum;
import com.yxcheng.token.common.exception.AcceptException;
import com.yxcheng.token.common.exception.LimitException;
import com.yxcheng.token.common.exception.MyBaseException;
import com.yxcheng.token.common.model.BaseJsonModel;
import com.yxcheng.token.common.model.JsonResult;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.bind.annotation.ResponseStatus;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.Map;

public class BaseGlobalExceptionHandler
{
    private final Logger logger = LoggerFactory.getLogger(getClass());
    protected static final String DEFAULT_ERROR_MESSAGE = "系统异常，请稍后再试";

    protected JsonResult<BaseJsonModel> handleError(HttpServletRequest req, HttpServletResponse rsp, Exception e)
            throws Exception
    {
        //异常时输入请求参数
        String contentType = req.getContentType();//获取请求的content-type
        if(StringUtils.isNotBlank(contentType) && (contentType.contains("multipart/form-data") || contentType.contains("application/json"))){//文件上传请求 json传输 *特殊请求
            //上传文件获取第一个入参对象。
            this.logger.warn("Request: {} raised exception params:{}", new Object[] { req.getRequestURI(), charReader(req)});
        }else{//非文件上传请求
            Map paramsMap  = req.getParameterMap();
            this.logger.warn("Request: {} raised exception params:{}", new Object[] { req.getRequestURI(), JSONObject.toJSONString(paramsMap)});
        }

        String errorMsg = "";
        String errorCode = "-1";
        JsonResult<BaseJsonModel> result = null;
        if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null) {
            throw e;
        }
        if ((e instanceof UndeclaredThrowableException)) {
            e = (Exception)((UndeclaredThrowableException)e).getUndeclaredThrowable();
        }
        if ((e instanceof MyBaseException))
        {
            errorCode = ((MyBaseException)e).getErrorCode();
            errorMsg = ((MyBaseException)e).getErrorMsg();
            result = new JsonResult((MyBaseException)e);
            this.logger.warn("Request: {} raised exception errcode:{} errmsg:{}", new Object[] { req.getRequestURI(), errorCode, errorMsg });
        }
        if(e instanceof LimitException){
            result = new JsonResult().errorResponse(ResultEnum.limit_access);
        }
        else
        {
            errorMsg = e.getMessage() != null ? e.getMessage() : DEFAULT_ERROR_MESSAGE;
            AcceptException sysException = new AcceptException(AcceptErrorEnum.SYSTEM_ERROR);
            result = new JsonResult(sysException);
            this.logger.error("Request: {} raised exception errcode:{} errmsg:{}", new Object[] { req.getRequestURI(), errorCode, errorMsg });
        }
        return result;
    }

    protected JsonResult<BaseJsonModel> handleMyError(HttpServletRequest req, HttpServletResponse rsp, MyBaseException e)
            throws Exception
    {
        String errorMsg = "";
        String errorCode = "-1";
        JsonResult<BaseJsonModel> result = null;

        errorCode = e.getErrorCode();
        errorMsg = e.getErrorMsg();
        result = new JsonResult(e);

        this.logger.warn("Request: {} raised exception errcode:{} errmsg:{}", new Object[] { req.getRequestURI(), errorCode, errorMsg });

        return result;
    }

    public String charReader(HttpServletRequest request) {
        BufferedReader br = null;
        String str, wholeStr = "";
        try {
            br = request.getReader();
            while((str = br.readLine()) != null){
                wholeStr += str;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return wholeStr;
    }
}
