/**
 * 全局异常处理器。
 *
 * <p>将各类异常统一转换为标准的接口响应结构，并设置对应的 HTTP 状态码。</p>
 */
package com.hertz.common.exception;

import com.hertz.common.api.ApiResponse;
import jakarta.validation.ConstraintViolationException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.AuthenticationException;
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.servlet.resource.NoResourceFoundException;

@RestControllerAdvice
public class GlobalExceptionHandler {

  @ExceptionHandler(BusinessException.class)
  public ResponseEntity<ApiResponse<Void>> handleBusinessException(BusinessException e) {
    var status = HttpStatus.BAD_REQUEST;
    if (e.getCode() == 40100) {
      status = HttpStatus.UNAUTHORIZED;
    } else if (e.getCode() == 40300) {
      status = HttpStatus.FORBIDDEN;
    } else if (e.getCode() == 50300) {
      status = HttpStatus.SERVICE_UNAVAILABLE;
    }
    return ResponseEntity.status(status).body(ApiResponse.fail(e.getCode(), e.getMessage()));
  }

  @ExceptionHandler(MethodArgumentNotValidException.class)
  @ResponseStatus(HttpStatus.BAD_REQUEST)
  public ApiResponse<Void> handleMethodArgumentNotValid(MethodArgumentNotValidException e) {
    var first = e.getBindingResult().getFieldErrors().stream().findFirst().orElse(null);
    var message = first == null ? "参数错误" : first.getDefaultMessage();
    return ApiResponse.fail(40001, message);
  }

  @ExceptionHandler(ConstraintViolationException.class)
  @ResponseStatus(HttpStatus.BAD_REQUEST)
  public ApiResponse<Void> handleConstraintViolation(ConstraintViolationException e) {
    return ApiResponse.fail(40001, e.getMessage());
  }

  @ExceptionHandler(AuthenticationException.class)
  @ResponseStatus(HttpStatus.UNAUTHORIZED)
  public ApiResponse<Void> handleAuthentication(AuthenticationException e) {
    return ApiResponse.fail(40100, "未登录或登录已过期");
  }

  @ExceptionHandler(AccessDeniedException.class)
  @ResponseStatus(HttpStatus.FORBIDDEN)
  public ApiResponse<Void> handleAccessDenied(AccessDeniedException e) {
    return ApiResponse.fail(40300, "无权限");
  }

  @ExceptionHandler(NoResourceFoundException.class)
  @ResponseStatus(HttpStatus.NOT_FOUND)
  public ApiResponse<Void> handleNoResourceFoundException(NoResourceFoundException e) {
    return ApiResponse.fail(40400, "资源未找到");
  }

  @ExceptionHandler(Exception.class)
  @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
  public ApiResponse<Void> handleException(Exception e) {
    e.printStackTrace(); // 打印堆栈信息到控制台
    return ApiResponse.fail(50000, "系统异常");
  }
}
