package com.cool.store.handler;


import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.cool.store.constants.CommonConstants;
import com.cool.store.exception.ApiException;
import com.cool.store.exception.ServiceException;
import com.cool.store.response.ResponseResult;
import com.cool.store.utils.UUIDUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import org.springframework.http.HttpStatus;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author zhangchenbiao
 * @FileName: CustomExceptionHandler
 * @Description: 自定义异常处理
 * @date 2023-06-13 19:42
 */
@Slf4j
@RestControllerAdvice
public class CustomExceptionHandler {

    @ExceptionHandler(value = ServiceException.class)
    public void handleCustomException(ServiceException e, HttpServletResponse httpServletResponse) {
        log.error(e.getMessage(), e);
        ResponseResult responseResult = new ResponseResult(e.getErrorCode(), e.getErrorMessage());
        responseResult(httpServletResponse, responseResult);
    }

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public void handleCustomException(MethodArgumentNotValidException e, HttpServletResponse httpServletResponse) {
        log.error(e.getMessage(), e);
        ResponseResult responseResult = new ResponseResult(500, String.join(",", getErrorMessages(e)));
        responseResult(httpServletResponse, responseResult);
    }

    private List<String> getErrorMessages(MethodArgumentNotValidException ex) {
        List<String> errors = new ArrayList<>();
        ex.getBindingResult().getAllErrors().forEach((error) -> {
            FieldError fieldError = (FieldError) error;
            errors.add(fieldError.getObjectName() + " " + fieldError.getDefaultMessage());
        });
        return errors;
    }

    @ExceptionHandler(value = ApiException.class)
    public void handleCustomException(ApiException e, HttpServletResponse httpServletResponse) {
        log.error(e.getMessage(), e);
        ResponseResult responseResult = new ResponseResult(e.getErrorCode(), e.getMessage());
        responseResult(httpServletResponse, responseResult);
    }

    @ExceptionHandler(value = Exception.class)
    public void handleException(Exception e, HttpServletResponse httpServletResponse) {
        log.error(e.getMessage(), e);
        ResponseResult responseResult = new ResponseResult(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage());
        responseResult(httpServletResponse, responseResult);
    }

    private void responseResult(HttpServletResponse response, ResponseResult result) {
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-type", "application/json;charset=UTF-8");
        String requestId = MDC.get(CommonConstants.REQUEST_ID);
        if(StringUtils.isBlank(requestId)){
            requestId = UUIDUtils.get32UUID();
        }
        result.setRequestId(requestId);
        result.setData(null);
        try {
            response.getWriter().write(JSONObject.toJSONString(result, SerializerFeature.WriteNullStringAsEmpty));
        } catch (IOException ex) {
            log.error(ex.getMessage(),ex);
        }
    }

}
