package com.xingxi.api.configuration;


import com.xingxi.common.exception.BusinessException;
import com.xingxi.api.common.ApiException;
import com.xingxi.api.common.ResponseDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.FileUploadException;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.List;

@Slf4j
@Order(Ordered.HIGHEST_PRECEDENCE)
@RestControllerAdvice(basePackages = "com.xingxi.store.controller")
@RequiredArgsConstructor
class DefaultHandlerExceptionResolver {
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public ResponseDTO<Void> handleMissingServletRequestParameterException(MissingServletRequestParameterException e, HttpServletRequest request) {
        e.printStackTrace();
        String requestId = (String) request.getAttribute("X-REQUEST-ID");
        ResponseDTO<Void> apiResultDTO = new ResponseDTO<>(400);
        apiResultDTO.setRequestId(requestId);
        apiResultDTO.setMessage("请求参数" + e.getParameterName() + "不能为空");
        return apiResultDTO;
    }

    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(ServletRequestBindingException.class)
    public ResponseDTO<Void> handleServletRequestBindingException(ServletRequestBindingException e, HttpServletRequest request) {
        e.printStackTrace();
        String requestId = (String) request.getAttribute("X-REQUEST-ID");
        ResponseDTO<Void> apiResultDTO = new ResponseDTO<>(500);
        apiResultDTO.setRequestId(requestId);
        apiResultDTO.setMessage(e.getMessage());
//        operLogService.handleAfterLog(apiResultDTO, request);
        return apiResultDTO;
    }

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public ResponseDTO<Void> handleHttpMessageNotReadableException(HttpMessageNotReadableException e, HttpServletRequest request) {
        e.printStackTrace();
        String requestId = (String) request.getAttribute("X-REQUEST-ID");
        ResponseDTO<Void> apiResultDTO = new ResponseDTO<>(400);
        apiResultDTO.setRequestId(requestId);
        apiResultDTO.setMessage("参数体不能为空");
//        operLogService.handleAfterLog(apiResultDTO, request);
        return apiResultDTO;
    }

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(BindException.class)
    public ResponseDTO<Void> handleBindException(BindException e, HttpServletRequest request) {
        e.printStackTrace();
        String message = "unknow error";
        BindingResult exceptions = e.getBindingResult();

        if (exceptions.hasErrors()) {
            List<ObjectError> errors = exceptions.getAllErrors();
            if (!errors.isEmpty()) {
                FieldError fieldError = (FieldError) errors.get(0);
                message =  fieldError.getDefaultMessage();
            }
        }

        String requestId = (String) request.getAttribute("X-REQUEST-ID");
        ResponseDTO<Void> apiResultDTO = new ResponseDTO<>(400);
        apiResultDTO.setRequestId(requestId);
        apiResultDTO.setMessage(message);
//        operLogService.handleAfterLog(apiResultDTO, request);
        return apiResultDTO;
    }

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseDTO<Void> handleMethodArgumentNotValidException(MethodArgumentNotValidException e, HttpServletRequest request) {
        e.printStackTrace();
        String message = "unknow error";
        BindingResult exceptions = e.getBindingResult();

        if (exceptions.hasErrors()) {
            List<ObjectError> errors = exceptions.getAllErrors();
            if (!errors.isEmpty()) {
                FieldError fieldError = (FieldError) errors.get(0);
                message = fieldError.getDefaultMessage();
            }
        }

        String requestId = (String) request.getAttribute("X-REQUEST-ID");
        ResponseDTO<Void> apiResultDTO = new ResponseDTO<>(400);
        apiResultDTO.setRequestId(requestId);
        apiResultDTO.setMessage(message);
//        operLogService.handleAfterLog(apiResultDTO, request);
        return apiResultDTO;
    }

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(ApiException.class)
    public ResponseDTO<Void> handleApiException(ApiException e, HttpServletRequest request) {
        e.printStackTrace();
        String message = e.getMessage() != null ? e.getMessage() : "System error";
        String requestId = (String) request.getAttribute("X-REQUEST-ID");
        ResponseDTO<Void> apiResultDTO = new ResponseDTO<>(400);
        apiResultDTO.setRequestId(requestId);
        apiResultDTO.setMessage(message);

//        ContentCachingRequestWrapper wrapper = (ContentCachingRequestWrapper) request;
//        byte[] contentAsByteArray = wrapper.getContentAsByteArray();
//        if (contentAsByteArray.length > 0) {
//            System.out.println(new String(contentAsByteArray));
//        }
//

//        operLogService.handleAfterLog(apiResultDTO, request);
        return apiResultDTO;
    }

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(BusinessException.class)
    public ResponseDTO<Void> handleBusinessException(BusinessException e, HttpServletRequest request) {
        e.printStackTrace();
        String message = e.getMessage() != null ? e.getMessage() : "System error";
        String requestId = (String) request.getAttribute("X-REQUEST-ID");
        ResponseDTO<Void> apiResultDTO = new ResponseDTO<>(400);
        apiResultDTO.setRequestId(requestId);
        apiResultDTO.setMessage(message);

//        ContentCachingRequestWrapper wrapper = (ContentCachingRequestWrapper) request;
//        byte[] contentAsByteArray = wrapper.getContentAsByteArray();
//        if (contentAsByteArray.length > 0) {
//            System.out.println(new String(contentAsByteArray));
//        }
//

//        operLogService.handleAfterLog(apiResultDTO, request);
        return apiResultDTO;
    }

    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler({Exception.class, FileUploadException.class, IOException.class})
    public ResponseDTO<Void> handleException(Exception e, HttpServletRequest request) {
        e.printStackTrace();
        String message = e.getMessage() != null ? e.getMessage() : "System error";
        String requestId = (String) request.getAttribute("X-REQUEST-ID");
        ResponseDTO<Void> apiResultDTO = new ResponseDTO<>(500);
        apiResultDTO.setRequestId(requestId);
        apiResultDTO.setMessage(message);
//        operLogService.handleAfterLog(apiResultDTO, request);
        return apiResultDTO;
    }
}
