/**
 * $Id: RestControllerAdviceHandler.java 13331 2016-07-06 09:09:33Z anjiabin $
 * Copyright(C) 2014-2020 easegame, All Rights Reserved.
 */
package com.liquidnet.common.exception;

import com.alibaba.fastjson.JSON;
import com.liquidnet.common.exception.constant.ErrorCode;
import com.liquidnet.common.exception.entity.Error;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

/**
 * @author AnJiabin <jiabin.an@lightnet.io>
 * @version V1.0
 * @Description: TODO
 * @class: RestControllerAdviceHandler
 * @Package com.liquidnet.common.exception
 * @Copyright: LightNet @ Copyright (c) 2020
 * @date 2020/9/21 10:37
 */
@ControllerAdvice(annotations = RestController.class)
public class RestControllerAdviceHandler {
    private final Logger logger = LoggerFactory.getLogger(RestControllerAdviceHandler.class);

    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public ResponseEntity<Error> serviceExceptionHandler(Exception rex, HttpServletRequest req) {
        logger.error("Ex.Handler.RestController:uri:{},param:{},ex:{},msg:{},",
                req.getRequestURI(), JSON.toJSONString(req.getParameterMap()), rex.getClass().getSimpleName(), rex.getLocalizedMessage());

        if (rex instanceof HttpMessageNotReadableException) {
            return new ResponseEntity<>(Error.getNew().setCode(ErrorCode.HTTP_PARAM_ERROR.getCode()).setMessage(ErrorCode.HTTP_PARAM_ERROR.getMessage()), HttpStatus.OK);
        }
        if (rex instanceof MissingServletRequestParameterException) {
            MissingServletRequestParameterException ygex = (MissingServletRequestParameterException) rex;
            String message = ygex.getMessage();
            return new ResponseEntity<>(Error.getNew().setCode(ErrorCode.HTTP_PARAM_ERROR.getCode()).setMessage(message), HttpStatus.OK);
        }
        if (rex instanceof ConstraintViolationException) {
            ConstraintViolationException ygex = (ConstraintViolationException) rex;
            ConstraintViolation violation = (ConstraintViolation) ygex.getConstraintViolations().toArray()[0];
            String violationNode = violation.getPropertyPath().toString();
//            String message = violationNode.substring(violationNode.indexOf(".") + 1) + violation.getMessage();
            String message = violation.getMessage();
            return new ResponseEntity<>(Error.getNew().setCode(ErrorCode.HTTP_PARAM_ERROR.getCode()).setMessage(message), HttpStatus.OK);
        }
        if (rex instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException ygex = (MethodArgumentNotValidException) rex;
            FieldError fieldError = ygex.getBindingResult().getFieldErrors().get(0);
//            String message = fieldError.getField() + " " + fieldError.getDefaultMessage();
            String message = fieldError.getDefaultMessage();
            return new ResponseEntity<>(Error.getNew().setCode(ErrorCode.HTTP_PARAM_ERROR.getCode()).setMessage(message), HttpStatus.OK);
        }
        if (rex instanceof LiquidnetFeignException) {
            LiquidnetFeignException ygex = (LiquidnetFeignException) rex;
            String errorCode = ygex.errorCode().getCode();
            String message = ygex.getMessage();
            message = message == null ? ygex.errorCode().getMessage() : message;
            return new ResponseEntity<>(Error.getNew().setCode(errorCode).setMessage(message), HttpStatus.OK);
        }
        if (rex instanceof LiquidnetServiceException) {
            LiquidnetServiceException ygex = (LiquidnetServiceException) rex;
            String errorCode = ygex.getCode();
            String message = ygex.getMessage();
            return new ResponseEntity<>(Error.getNew().setCode(errorCode).setMessage(message), HttpStatus.OK);
        } else {
            logger.error("Unprocessed exception", rex);
//            return new ResponseEntity<Error>(new Error(ErrorCode.HTTP_SYSTEM_ERROR.getCode(), ErrorCode.HTTP_SYSTEM_ERROR.getMessage()), HttpStatus.OK);
            return new ResponseEntity<Error>(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }
}
