package com.auth.common.exception;

import com.auth.common.context.BaseContext;
import com.auth.common.model.common.result.Result;
import com.auth.common.model.common.result.ResultCodeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.security.authorization.AuthorizationDeniedException;
import org.springframework.util.StringUtils;
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.nio.file.AccessDeniedException;
import java.sql.SQLException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(AuthenticSecurityException.class)
    @ResponseBody
    public Result<Object> exceptionHandler(AuthenticSecurityException exception) {
        String message = exception.getMessage();
        Integer code = exception.getCode();
        return Result.error(null, code, message);
    }

    @ExceptionHandler(RuntimeException.class)
    @ResponseBody
    public Result<Object> exceptionHandler(RuntimeException exception) {
        String message = exception.getMessage();
        message = StringUtils.hasText(message) ? message : "服务器异常";
        log.error("发生业务异常: {}", exception.getMessage(), exception);

        // 💡IDEA：如果需要特殊情况的日志可以参考下面的代码
        // =========================================
        // StringWriter sw = new StringWriter();
        // e.printStackTrace(new PrintWriter(sw));
        // logger.error(sw.toString());
        // =========================================

        // 解析异常
        String jsonParseError = "JSON parse error (.*)";
        Matcher jsonParseErrorMatcher = Pattern.compile(jsonParseError).matcher(message);
        if (jsonParseErrorMatcher.find()) {
            return Result.error(null, 500, "JSON解析异常 " + jsonParseErrorMatcher.group(1));
        }

        // 数据过大
        String dataTooLongError = "Data too long for column (.*?) at row 1";
        Matcher dataTooLongErrorMatcher = Pattern.compile(dataTooLongError).matcher(message);
        if (dataTooLongErrorMatcher.find()) {
            return Result.error(null, 500, dataTooLongErrorMatcher.group(1) + " 字段数据过大");
        }

        // 主键冲突
        String primaryKeyError = "Duplicate entry '(.*?)' for key .*";
        Matcher primaryKeyErrorMatcher = Pattern.compile(primaryKeyError).matcher(message);
        if (primaryKeyErrorMatcher.find()) {
            return Result.error(null, 500, "[" + primaryKeyErrorMatcher.group(1) + "]已存在");
        }

        log.error("GlobalExceptionHandler===>运行时异常信息：{}", message);
        return Result.error(null, 500, message);
    }

    // 表单验证字段
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result<String> handleValidationExceptions(MethodArgumentNotValidException ex) {
        log.error("表单验证失败，用户Id：{}", BaseContext.getUserId());
        String errorMessage = ex.getBindingResult().getFieldErrors().stream()
                .map(DefaultMessageSourceResolvable::getDefaultMessage)
                .collect(Collectors.joining(", "));
        return Result.error(null, 201, errorMessage);
    }

    // 特定异常处理
    @ExceptionHandler(ArithmeticException.class)
    @ResponseBody
    public Result<Object> error(ArithmeticException exception) {
        log.error("GlobalExceptionHandler===>特定异常信息：{}", exception.getMessage());

        return Result.error(null, 500, exception.getMessage());
    }

    // spring security异常
    @ExceptionHandler(AccessDeniedException.class)
    @ResponseBody
    public Result<String> error(AccessDeniedException exception) {
        log.error("GlobalExceptionHandler===>spring security异常：{}", exception.getMessage());

        return Result.error(ResultCodeEnum.FAIL_NO_ACCESS_DENIED);
    }

    // spring security异常
    @ExceptionHandler(AuthorizationDeniedException.class)
    @ResponseBody
    public Result<String> error(AuthorizationDeniedException exception) {
        log.warn("AuthorizationDeniedException===>spring security异常：{}", exception.getMessage());

        return Result.error(ResultCodeEnum.FAIL_NO_ACCESS_DENIED);
    }

    // 处理SQL异常
    @ExceptionHandler(SQLException.class)
    @ResponseBody
    public Result<String> exceptionHandler(SQLException exception) {
        log.error("GlobalExceptionHandler===>处理SQL异常:{}", exception.getMessage());

        String message = exception.getMessage();
        if (message.contains("Duplicate entry")) {
            // 错误信息
            return Result.error(ResultCodeEnum.USER_IS_EMPTY);
        } else {
            return Result.error(ResultCodeEnum.UNKNOWN_EXCEPTION);
        }
    }

}
