package top.tqx.demo_1.handler;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.async.AsyncRequestNotUsableException;
import org.springframework.web.context.request.async.AsyncRequestTimeoutException;
import top.tqx.demo_1.common.Result;
import top.tqx.demo_1.exception.PermissionDeniedException;

import java.io.IOException;
import java.nio.file.AccessDeniedException;

@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(AsyncRequestTimeoutException.class)
    @ResponseStatus(HttpStatus.GONE)
    public void handleAsyncRequestTimeoutException(AsyncRequestTimeoutException e) {
        log.warn("SSE连接超时，已自动断开: {}", e.getMessage());
    }

    @ExceptionHandler(AsyncRequestNotUsableException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public void handleAsyncRequestNotUsableException(AsyncRequestNotUsableException e) {
        if (e.getMessage() != null && e.getMessage().contains("Connection reset")) {
            log.debug("客户端提前断开连接: Connection reset by peer");
        } else {
            log.warn("异步请求不可用: {}", e.getMessage());
        }
    }

    @ExceptionHandler(IOException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public void handleIOException(IOException e) {
        if (e.getMessage() != null && e.getMessage().contains("Connection reset")) {
            log.debug("客户端提前断开连接: Connection reset by peer");
        } else {
            log.warn("IO异常: {}", e.getMessage());
        }
    }

    @ExceptionHandler(PermissionDeniedException.class)
    @ResponseStatus(HttpStatus.FORBIDDEN)
    public Result<Void> handlePermissionDeniedException(PermissionDeniedException e) {
        log.warn("权限拒绝: {}", e.getMessage());
        return Result.error(403, "无权限访问");
    }

    @ExceptionHandler(AccessDeniedException.class)
    @ResponseStatus(HttpStatus.FORBIDDEN)
    public Result<Void> handleAccessDeniedException(AccessDeniedException e) {
        log.warn("访问拒绝: {}", e.getMessage());
        return Result.error(403, "访问被拒绝");
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Result<Void> handleValidationException(MethodArgumentNotValidException e) {
        String message = e.getBindingResult().getFieldErrors().stream()
            .map(error -> error.getField() + ": " + error.getDefaultMessage())
            .findFirst()
            .orElse("参数验证失败");
        log.warn("参数验证失败: {}", message);
        return Result.error(400, message);
    }

    @ExceptionHandler(BindException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Result<Void> handleBindException(BindException e) {
        String message = e.getBindingResult().getFieldErrors().stream()
            .map(error -> error.getField() + ": " + error.getDefaultMessage())
            .findFirst()
            .orElse("参数绑定失败");
        log.warn("参数绑定失败: {}", message);
        return Result.error(400, message);
    }

    @ExceptionHandler(RuntimeException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Result<Void> handleRuntimeException(RuntimeException e) {
        log.error("运行时异常: type={}, message={}", e.getClass().getSimpleName(), e.getMessage());
        if (e.getMessage() != null && (e.getMessage().contains("SQL") || e.getMessage().contains("connection"))) {
            return Result.error(500, "数据库操作失败");
        }
        if (e.getMessage() != null && e.getMessage().contains("Access Denied")) {
            return Result.error(403, "无权限访问");
        }
        return Result.error(500, "服务器内部错误");
    }

    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Result<Void> handleException(Exception e) {
        log.error("系统异常: type={}, message={}", e.getClass().getSimpleName(), e.getMessage(), e);
        if (e.getCause() != null) {
            String causeMsg = e.getCause().getMessage();
            if (causeMsg != null && causeMsg.contains("Access Denied")) {
                return Result.error(403, "无权限访问");
            }
        }
        return Result.error(500, "系统异常");
    }
}
