package ink.wgink.common.advice;

import com.alibaba.fastjson.JSON;
import ink.wgink.exceptions.*;
import ink.wgink.exceptions.base.SystemException;
import ink.wgink.exceptions.rpc.RemoteRequestException;
import ink.wgink.exceptions.rpc.RemoteResponseException;
import ink.wgink.interfaces.consts.ISystemConstant;
import ink.wgink.pojo.result.ErrorResult;
import ink.wgink.util.AesUtil;
import ink.wgink.util.ReflectUtil;
import ink.wgink.util.map.HashMapUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.sql.SQLSyntaxErrorException;
import java.util.ArrayList;
import java.util.List;


/**
 * @ClassName: ResponseAdvice
 * @Description: Response结果处理
 * @Author: WangGeng
 * @Date: 2019/2/26 5:14 PM
 * @Version: 1.0
 **/
@ControllerAdvice
public class ResponseAdvice {

    private static final Logger LOG = LoggerFactory.getLogger(ResponseAdvice.class);

    @ResponseBody
    @ExceptionHandler({SystemException.class, SQLSyntaxErrorException.class, HashMapUtil.TypeConversionException.class, ReflectUtil.ReflectException.class})
    public void responseException(HttpServletRequest request, HttpServletResponse response, Exception e) throws IOException, ServletException {
        if (e instanceof FileException) {
            LOG.error(e.getMessage());
        } else if (e instanceof ParamsException) {
            LOG.error(e.getMessage());
        } else {
            LOG.error(e.getMessage(), e);
        }
        ErrorResult result = new ErrorResult(ErrorResult.ErrorResultCodeEnum.SYSTEM_ERROR.getValue(), "系统错误");
        if (e instanceof SaveException) {
            result.setCode(ErrorResult.ErrorResultCodeEnum.SAVE_ERROR.getValue());
        } else if (e instanceof RemoveException) {
            result.setCode(ErrorResult.ErrorResultCodeEnum.REMOVE_ERROR.getValue());
        } else if (e instanceof UpdateException) {
            result.setCode(ErrorResult.ErrorResultCodeEnum.UPDATE_ERROR.getValue());
        } else if (e instanceof SearchException) {
            result.setCode(ErrorResult.ErrorResultCodeEnum.QUERY_ERROR.getValue());
        } else if (e instanceof ParamsException) {
            result.setCode(ErrorResult.ErrorResultCodeEnum.PARAMS_ERROR.getValue());
        } else if (e instanceof FileException) {
            result.setCode(ErrorResult.ErrorResultCodeEnum.FILE_ERROR.getValue());
        } else if (e instanceof AppTokenException) {
            result.setCode(ErrorResult.ErrorResultCodeEnum.APP_DEPENDENCY_ERROR.getValue());
        } else if (e instanceof AppDeviceException) {
            result.setCode(ErrorResult.ErrorResultCodeEnum.DEVICE_ERROR.getValue());
        } else if (e instanceof AppVersionException) {
            result.setCode(ErrorResult.ErrorResultCodeEnum.DEVICE_VERSION_ERROR.getValue());
        } else if (e instanceof PropertiesException) {
            result.setCode(ErrorResult.ErrorResultCodeEnum.PROPERTIES_ERROR.getValue());
        } else if (e instanceof AccessTokenException) {
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
        } else if (e instanceof RemoteRequestException) {
            response.setStatus(ErrorResult.ErrorResultCodeEnum.REMOTE_REQUEST_EXCEPTION.getValue());
        } else if (e instanceof RemoteResponseException) {
            response.setStatus(ErrorResult.ErrorResultCodeEnum.REMOTE_RESPONSE_EXCEPTION.getValue());
        } else if (e instanceof OaNodeException) {
            response.setStatus(ErrorResult.ErrorResultCodeEnum.OA_NODE_EXCEPTION.getValue());
        }
        // 自定义提示信息
        if (e instanceof SystemException) {
            result.setMsg(e.getMessage());
        } else if (e instanceof UnsupportedEncodingException) {
            result.setCode(ErrorResult.ErrorResultCodeEnum.ENCODE_ERROR.getValue());
            result.setMsg(e.getMessage());
        } else if (e instanceof AesUtil.AesEncodeException) {
            result.setCode(ErrorResult.ErrorResultCodeEnum.ENCODE_ERROR.getValue());
            result.setMsg(e.getMessage());
        } else if (e instanceof AesUtil.AesDecodeException) {
            result.setCode(ErrorResult.ErrorResultCodeEnum.DECODE_ERROR.getValue());
            result.setMsg(e.getMessage());
        } else if (e instanceof ReflectUtil.ReflectException) {
            result.setCode(ErrorResult.ErrorResultCodeEnum.SYSTEM_ERROR.getValue());
        } else {
            StringBuilder errorMessageSB = new StringBuilder();
            for (StackTraceElement stackTraceElement : e.getStackTrace()) {
                errorMessageSB.append(stackTraceElement.toString()).append("\n");
            }
            result.setDetail(errorMessageSB.toString());
            result.setDetail(e.getMessage());
        }
        String contentType = request.getContentType();
        if (contentType != null && contentType.contains(MediaType.APPLICATION_JSON_VALUE)) {
            response.setCharacterEncoding(ISystemConstant.CHARSET_UTF8);
            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
            response.setStatus(HttpStatus.BAD_REQUEST.value());
            response.getWriter().write(JSON.toJSONString(result));
        } else {
            request.getSession().setAttribute("errorMessage", JSON.toJSONString(result));
            if (!response.isCommitted()) {
                StackTraceElement[] stackTraces = e.getStackTrace();
                List<String> errorStackTraces = new ArrayList();
                for (StackTraceElement stackTraceElement : stackTraces) {
                    errorStackTraces.add(stackTraceElement.toString());
                }
                request.getSession().setAttribute("errorStackTraces", errorStackTraces);
                request.getRequestDispatcher("/error/exception").forward(request, response);
            }
        }
    }

}
