package com.kym.common.handler;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
import com.kym.common.R;
import com.kym.common.exception.BaseException;
import com.kym.common.exception.BusinessException;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
import jakarta.validation.ValidationException;
import org.apache.ibatis.jdbc.Null;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.stream.Collectors;

import static com.kym.common.constant.ResponseEnum.LOGIN_FAILED;
import static com.kym.common.constant.ResponseEnum.NO_PERMISSION;

/**
 * 全局异常处理
 *
 * @author skyline
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    private static final Logger LOGGER = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * 业务异常
     *
     * @param e 异常
     * @return 异常结果
     */
    @ExceptionHandler(value = BusinessException.class)
    @ResponseBody
    public R<?> handleBusinessException(BaseException e) {
        LOGGER.error(e.getMessage(),e);
        return R.failed(e.getCode(), e.getMessage());
    }

    /**
     * 自定义异常
     *
     * @param e 异常
     * @return 异常结果
     */
    @ExceptionHandler(value = BaseException.class)
    @ResponseBody
    public R<Null> handleBaseException(BaseException e) {

        LOGGER.error(e.getMessage(), e);
        return R.failed();
    }


    /**
     * 登录异常
     *
     * @param e 异常
     * @return 异常结果
     */
    @ExceptionHandler(value = NotLoginException.class)
    @ResponseBody
    public R<?> handleLoginException(NotLoginException e) {

        var message = "";
        if (e.getType().equals(NotLoginException.NOT_TOKEN)) {
            message = NotLoginException.NOT_TOKEN_MESSAGE;
        } else if (e.getType().equals(NotLoginException.INVALID_TOKEN)) {
            message = NotLoginException.INVALID_TOKEN_MESSAGE;
        } else if (e.getType().equals(NotLoginException.TOKEN_TIMEOUT)) {
            message = NotLoginException.TOKEN_TIMEOUT_MESSAGE;
        } else if (e.getType().equals(NotLoginException.BE_REPLACED)) {
            message = NotLoginException.BE_REPLACED_MESSAGE;
        } else if (e.getType().equals(NotLoginException.KICK_OUT)) {
            message = NotLoginException.KICK_OUT_MESSAGE;
        } else if (e.getType().equals(NotLoginException.TOKEN_FREEZE)) {
            message = NotLoginException.TOKEN_FREEZE_MESSAGE;
        } else if (e.getType().equals(NotLoginException.NO_PREFIX)) {
            message = NotLoginException.NO_PREFIX_MESSAGE;
        } else {
            message = NotLoginException.DEFAULT_MESSAGE;
        }
        LOGGER.error("登录异常:" + message, e);
        return R.failed(LOGIN_FAILED.getCode(), message);
    }

    /**
     * 校验异常处理
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = {BindException.class, ValidationException.class})
    public R<?> handleValidatedException(Exception e) {
        String message = "";
        if (e instanceof MethodArgumentNotValidException) {
//            message = ((MethodArgumentNotValidException) e).getBindingResult().getAllErrors().stream()
//                    .map(ObjectError::getDefaultMessage)
//                    .collect(Collectors.joining("; "));

                FieldError firstError = ((MethodArgumentNotValidException) e).getBindingResult().getFieldErrors().get(0);
                return R.failed(HttpStatus.BAD_REQUEST.value(),firstError.getDefaultMessage());

        } else if (e instanceof ConstraintViolationException) {
            message = ((ConstraintViolationException) e).getConstraintViolations().stream()
                    .map(ConstraintViolation::getMessage)
                    .collect(Collectors.joining("; "));
        } else if (e instanceof BindException) {
            message = ((BindException) e).getAllErrors().stream().map(ObjectError::getDefaultMessage)
                    .collect(Collectors.joining("; "));
        }
        LOGGER.error(e.getMessage(), e);
        return R.failed(HttpStatus.BAD_REQUEST.value(), message);
    }

    @ExceptionHandler(value = {NotRoleException.class, NotPermissionException.class})
    public R handlerException(Exception e) {
        LOGGER.info(e.getMessage(), e);
        return R.failed(NO_PERMISSION);
    }


    @ExceptionHandler(value = {Exception.class})
    public R handlerRestException(Exception e) {
        LOGGER.error("系统异常: {}", e.getMessage(), e);
        return R.failed(500, "系统繁忙，请稍后重试");  // 不暴露详细错误
    }


}
