<?php

namespace Kylin\Core;

use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException as LaravelValidationException;
use Kylin\Core\Exceptions\BusinessException;
use Kylin\Core\Exceptions\KylinException;
use Kylin\Core\Exceptions\ValidationException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Throwable;

/**
 * API 异常统一处理器
 *
 * 将各类 PHP/Laravel 异常转换为统一的 JSON 响应格式，
 * 供 Laravel 异常处理器的 render() 方法调用。
 *
 * 支持处理的异常类型：
 *  - BusinessException / KylinException：业务异常，使用错误码体系
 *  - ValidationException：自定义验证异常
 *  - Laravel 内置验证异常、认证异常、授权异常
 *  - ModelNotFoundException / NotFoundHttpException：404 异常
 *  - 其他未知异常：500 内部错误
 */
class ApiExceptionHandler
{
    /**
     * 渲染异常响应
     *
     * 仅对 expectsJson() 的请求返回 JSON 格式响应，
     * 非 JSON 请求返回 null 交由框架默认处理。
     *
     * @param  Throwable  $e       捕获的异常
     * @param  Request    $request 当前请求
     * @return JsonResponse|null   返回 null 表示不处理此异常
     */
    public static function render(Throwable $e, Request $request): ?JsonResponse
    {
        if (! $request->expectsJson()) {
            return null;
        }

        if ($e instanceof BusinessException) {
            return ApiResponse::error(
                code: $e->errorCode()->value,
                message: $e->getMessage(),
                httpStatus: $e->getHttpStatusCode(),
            );
        }

        if ($e instanceof KylinException) {
            return ApiResponse::error(
                code: $e->errorCode()->value,
                message: $e->getMessage(),
                httpStatus: $e->getHttpStatusCode(),
            );
        }

        if ($e instanceof ValidationException) {
            return ApiResponse::error(
                code: $e->errorCode()->value,
                message: $e->getMessage(),
                httpStatus: 422,
                data: ['errors' => $e->getErrors()],
            );
        }

        if ($e instanceof LaravelValidationException) {
            return ApiResponse::error(
                code: 'CORE-VAL-001',
                message: '请求参数验证失败',
                httpStatus: 422,
                data: ['errors' => $e->errors()],
            );
        }

        if ($e instanceof AuthenticationException) {
            return ApiResponse::error(
                code: 'CORE-AUTH-001',
                message: '未认证或认证已过期',
                httpStatus: 401,
            );
        }

        if ($e instanceof AuthorizationException) {
            return ApiResponse::error(
                code: 'CORE-PERM-001',
                message: '无权执行此操作',
                httpStatus: 403,
            );
        }

        if ($e instanceof ModelNotFoundException) {
            return ApiResponse::error(
                code: 'CORE-SYS-002',
                message: '请求的资源不存在',
                httpStatus: 404,
            );
        }

        if ($e instanceof NotFoundHttpException) {
            return ApiResponse::error(
                code: 'CORE-SYS-002',
                message: '请求的接口不存在',
                httpStatus: 404,
            );
        }

        return ApiResponse::error(
            code: 'CORE-SYS-004',
            message: app()->hasDebugModeEnabled() ? $e->getMessage() : '服务器内部错误',
            httpStatus: 500,
        );
    }
}
