package com.sckw.core.exception;

import com.sckw.core.web.constant.HttpStatus;
import com.sckw.core.web.response.HttpResult;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.List;
import java.util.Set;

@Slf4j
@RestControllerAdvice
@Configuration
public class GlobalSystemExceptionHandler {

    @ExceptionHandler(value = SystemException.class)
    @ResponseBody
    public HttpResult handlerSystemException(SystemException e) {
        log.error("业务异常:", e);
        return HttpResult.error(e.getCode(), e.getMessage());
    }

    @ExceptionHandler(value = RuntimeException.class)
    @ResponseBody
    public HttpResult handlerRuntimeException(RuntimeException e) {
        log.error("业务异常:", e);
        return HttpResult.error(HttpStatus.GLOBAL_EXCEPTION_CODE, e.getMessage());
    }

    /**
     * BusinessException处理
     *
     * @param ex
     * @return
     */
    @ResponseBody
    @ExceptionHandler(BusinessException.class)
    public HttpResult businessExceptionHandler(BusinessException ex) {
        log.error("业务异常,message={},param={}", ex.getMsg(), ex.getParam());
        return HttpResult.error(HttpStatus.GLOBAL_EXCEPTION_CODE, ex.getMessage());
    }

    /**
     * 前端自定义提示异常
     *
     * @param ex
     * @return
     */
    @ResponseBody
    @ExceptionHandler(CustomPromptException.class)
    public HttpResult customPromptExceptionHandler(CustomPromptException ex) {
        log.error("前端自定义提示异常,code={},message={},param={}", ex.getCode(), ex.getMsg(), ex.getParam());
        return HttpResult.error(ex.getCode(), ex.getMessage());
    }


    /**
     * NotLoginException处理
     *
     * @param ex
     * @return
     */
    @ResponseBody
    @ExceptionHandler(NotLoginException.class)
    public HttpResult notLoginException(NotLoginException ex) {
        log.error("用户未登录, message={}, param={}", ex.getMsg(), ex.getParam());
        return HttpResult.error(HttpStatus.UN_LOGIN_CODE, HttpStatus.UN_LOGIN_MESSAGE, ex.getMessage());
    }

    @ResponseBody
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public HttpResult noArgs(MissingServletRequestParameterException ex) {
        String format = "参数:[%s]不能为空";
        return HttpResult.error(HttpStatus.PARAMETERS_PATTERN_ERROR_CODE, String.format(format, ex.getParameterName()));
    }

    /**
     * 注解校验异常处理
     *
     * @param ex
     * @return
     */
    @ResponseBody
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public HttpResult methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException ex) {
        List<FieldError> fieldErrors = ex.getBindingResult().getFieldErrors();
        StringBuilder sb = new StringBuilder();
        if (!CollectionUtils.isEmpty(fieldErrors)) {
            boolean first = true;
            for (FieldError fieldError : fieldErrors) {
                if (!first) {
                    sb.append(",");
                }
                sb.append(fieldError.getDefaultMessage());
                first = false;
            }
        }
        String errMsg = sb.toString();
        log.error("参数校验异常：{}", errMsg);
        return HttpResult.error(HttpStatus.PARAMETERS_PATTERN_ERROR_CODE, errMsg);
    }

    @ResponseBody
    @ExceptionHandler(ConstraintViolationException.class)
    public HttpResult constraintViolationExceptionHandler(ConstraintViolationException ex) {
        log.error("参数校验异常c：{}", ex.getMessage());
        Set<ConstraintViolation<?>> constraintViolations = ex.getConstraintViolations();
        StringBuilder sb = new StringBuilder();
        if (!CollectionUtils.isEmpty(constraintViolations)) {
            boolean first = true;
            for (ConstraintViolation<?> constraintViolation : constraintViolations) {
                if (!first) {
                    sb.append(",");
                }
                sb.append(constraintViolation.getMessage());
                first = false;
            }
        }
        return HttpResult.error(HttpStatus.PARAMETERS_PATTERN_ERROR_CODE, sb.toString());
    }

    /**
     * exception处理
     *
     * @param ex
     * @returnh
     */
    @ResponseBody
    @ExceptionHandler(Exception.class)
    public HttpResult defaultExceptionHandler(Exception ex) {
        log.error("系统异常", ex);
        return HttpResult.error(HttpStatus.GLOBAL_EXCEPTION_CODE, ex.toString());
    }

}

