<?php

declare(strict_types=1);

require_once base_path('app/repositories/catalog_repository.php');
require_once base_path('app/services/cache_service.php');
require_once base_path('app/services/rate_limiter.php');
require_once base_path('app/services/cart_service.php');
require_once base_path('app/services/order_service.php');
require_once base_path('app/services/stripe_service.php');
require_once base_path('app/services/image_service.php');
require_once base_path('app/services/auth_service.php');
require_once base_path('app/services/mail_service.php');
require_once base_path('app/services/rib_service.php');

function handle_request(): void
{
    apply_cors_headers();

    if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'OPTIONS') {
        http_response_code(204);
        return;
    }

    $globalLimit = rate_limit_check(
        'global:' . client_ip(),
        (int) config('app.rate_limit_per_minute', 120),
        60
    );
    send_rate_limit_headers($globalLimit);

    if (!$globalLimit['allowed']) {
        header('Retry-After: ' . (string) $globalLimit['retry_after']);
        error_response('Trop de requetes.', 429);
        return;
    }

    $method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
    $path = normalize_api_path(request_path());

    try {
        if ($method === 'GET' && ($path === '' || $path === '/')) {
            json_response([
                'success' => true,
                'service' => 'camparts-api',
                'version' => '1.0.0',
                'endpoints' => [
                'GET /api/articles',
                'GET /api/articles/{id}',
                'POST /api/articles',
                'PATCH /api/articles/{id}',
                'DELETE /api/articles/{id}',
                'GET /api/marques',
                'POST /api/marques',
                'GET /api/modeles?marque_id=',
                'POST /api/modeles',
                'GET /api/rib',
                'POST /api/rib',
                'POST /api/images/upload',
                'POST /api/auth/register',
                'POST /api/auth/login',
                'POST /api/auth/forgot',
                'POST /api/auth/logout',
                'GET /api/auth/me',
                'GET /api/auth/accounts',
                'PATCH /api/auth/accounts/{id}/approval',
                'POST /api/cart/add',
                'POST /api/cart/sync',
                'GET /api/cart',
                'POST /api/order/create',
                'POST /api/stripe/checkout',
                'POST /api/stripe/confirm',
                'POST /api/stripe/webhook',
                'GET /api/orders/mine',
                'GET /api/admin/orders',
                'PATCH /api/orders/{id}/status',
                    'GET /api/images/{reference}',
                ],
            ]);
            return;
        }

        if ($method === 'GET' && $path === 'articles') {
            endpoint_articles_list();
            return;
        }

        if ($method === 'GET' && preg_match('#^articles/(\d+)$#', $path, $matches) === 1) {
            endpoint_article_details((int) $matches[1]);
            return;
        }

        if ($method === 'PATCH' && preg_match('#^articles/(\d+)$#', $path, $matches) === 1) {
            endpoint_article_update((int) $matches[1]);
            return;
        }

        if ($method === 'DELETE' && preg_match('#^articles/(\d+)$#', $path, $matches) === 1) {
            endpoint_article_delete((int) $matches[1]);
            return;
        }

        if ($method === 'POST' && $path === 'articles') {
            endpoint_articles_create();
            return;
        }

        if ($method === 'GET' && $path === 'marques') {
            endpoint_marques();
            return;
        }

        if ($method === 'POST' && $path === 'marques') {
            endpoint_marques_create();
            return;
        }

        if ($method === 'GET' && $path === 'modeles') {
            endpoint_modeles();
            return;
        }

        if ($method === 'POST' && $path === 'modeles') {
            endpoint_modeles_create();
            return;
        }

        if ($method === 'GET' && $path === 'rib') {
            endpoint_rib_get();
            return;
        }

        if ($method === 'POST' && $path === 'rib') {
            endpoint_rib_update();
            return;
        }

        if ($method === 'POST' && $path === 'auth/register') {
            $limit = rate_limit_check(
                'auth_register:' . client_ip(),
                (int) config('app.rate_limit_auth_per_minute', 20),
                60
            );
            send_rate_limit_headers($limit);
            if (!$limit['allowed']) {
                header('Retry-After: ' . (string) $limit['retry_after']);
                error_response('Trop de requetes authentification.', 429);
                return;
            }

            endpoint_auth_register();
            return;
        }

        if ($method === 'POST' && $path === 'auth/login') {
            $limit = rate_limit_check(
                'auth_login:' . client_ip(),
                (int) config('app.rate_limit_auth_per_minute', 20),
                60
            );
            send_rate_limit_headers($limit);
            if (!$limit['allowed']) {
                header('Retry-After: ' . (string) $limit['retry_after']);
                error_response('Trop de requetes authentification.', 429);
                return;
            }

            endpoint_auth_login();
            return;
        }

        if ($method === 'POST' && $path === 'auth/forgot') {
            $limit = rate_limit_check(
                'auth_forgot:' . client_ip(),
                (int) config('app.rate_limit_auth_per_minute', 20),
                60
            );
            send_rate_limit_headers($limit);
            if (!$limit['allowed']) {
                header('Retry-After: ' . (string) $limit['retry_after']);
                error_response('Trop de requetes authentification.', 429);
                return;
            }

            endpoint_auth_forgot();
            return;
        }

        if ($method === 'POST' && $path === 'auth/logout') {
            endpoint_auth_logout();
            return;
        }

        if ($method === 'GET' && $path === 'auth/me') {
            endpoint_auth_me();
            return;
        }

        if ($method === 'GET' && $path === 'auth/accounts') {
            endpoint_auth_accounts();
            return;
        }

        if ($method === 'PATCH' && preg_match('#^auth/accounts/([^/]+)/approval$#', $path, $matches) === 1) {
            endpoint_auth_account_approval(rawurldecode($matches[1]));
            return;
        }

        if ($method === 'POST' && $path === 'cart/add') {
            endpoint_cart_add();
            return;
        }

        if ($method === 'GET' && $path === 'cart') {
            endpoint_cart_get();
            return;
        }

        if ($method === 'POST' && $path === 'cart/sync') {
            endpoint_cart_sync();
            return;
        }

        if ($method === 'POST' && $path === 'order/create') {
            endpoint_order_create();
            return;
        }

        if ($method === 'POST' && $path === 'stripe/checkout') {
            endpoint_stripe_checkout();
            return;
        }

        if ($method === 'POST' && $path === 'stripe/confirm') {
            endpoint_stripe_confirm();
            return;
        }

        if ($method === 'POST' && $path === 'stripe/webhook') {
            endpoint_stripe_webhook();
            return;
        }

        if ($method === 'GET' && $path === 'orders/mine') {
            endpoint_orders_mine();
            return;
        }

        if ($method === 'GET' && $path === 'admin/orders') {
            endpoint_admin_orders();
            return;
        }

        if ($method === 'PATCH' && preg_match('#^orders/([^/]+)/status$#', $path, $matches) === 1) {
            endpoint_order_status_update(rawurldecode($matches[1]));
            return;
        }

        if ($method === 'POST' && $path === 'images/upload') {
            endpoint_image_upload();
            return;
        }

        if ($method === 'GET' && preg_match('#^images/([A-Za-z0-9._\-%]{2,128})$#', $path, $matches) === 1) {
            $reference = rawurldecode($matches[1]);
            $width = query_int('w', 0, 0, 1600);
            $height = query_int('h', 0, 0, 1600);
            handle_image_request($reference, $width > 0 ? $width : null, $height > 0 ? $height : null);
            return;
        }

        if ($method === 'GET' && $path === 'image.php') {
            $reference = query_string('ref', '');
            if ($reference === null || $reference === '') {
                send_placeholder_image('NO-REF', null, null);
                return;
            }

            $width = query_int('w', 0, 0, 1600);
            $height = query_int('h', 0, 0, 1600);
            handle_image_request($reference, $width > 0 ? $width : null, $height > 0 ? $height : null);
            return;
        }

        error_response('Endpoint introuvable.', 404);
    } catch (InvalidArgumentException $exception) {
        error_response($exception->getMessage(), 422);
    } catch (DomainException $exception) {
        $status = (int) $exception->getCode();
        if ($status < 100 || $status > 599) {
            $status = 400;
        }
        error_response($exception->getMessage(), $status);
    } catch (RuntimeException $exception) {
        $status = str_contains(strtolower($exception->getMessage()), 'introuvable') ? 404 : 400;
        error_response($exception->getMessage(), $status);
    } catch (Throwable $exception) {
        $debug = (bool) config('app.debug', false);
        error_response(
            $debug ? $exception->getMessage() : 'Erreur serveur.',
            500,
            $debug ? ['trace' => $exception->getTraceAsString()] : []
        );
    }
}

function send_rate_limit_headers(array $limit): void
{
    header('X-RateLimit-Remaining: ' . (string) ($limit['remaining'] ?? 0));
    header('X-RateLimit-Retry-After: ' . (string) ($limit['retry_after'] ?? 0));
}

function endpoint_articles_list(): void
{
    $currentUser = auth_current_user();
    $isAdminRequest = is_array($currentUser) && (($currentUser['role'] ?? 'client') === 'admin');

    $filters = [
        'page' => query_int('page', 1, 1, 100000),
        'limit' => query_int('limit', 24, 1, 100),
        'q' => query_string('q', '') ?? '',
        'modele_id' => query_int('modele_id', 0, 0),
        'marque_id' => query_int('marque_id', 0, 0),
        'in_stock' => query_bool('in_stock', false),
        'sort' => query_string('sort', 'newest') ?? 'newest',
        'raw_stock' => $isAdminRequest,
    ];

    $payload = repo_list_articles($filters);

    json_response([
        'success' => true,
        'data' => $payload,
    ]);
}

function endpoint_article_details(int $articleId): void
{
    if ($articleId <= 0) {
        error_response('ID article invalide.', 422);
        return;
    }

    $article = repo_get_article($articleId);
    if ($article === null) {
        error_response('Article introuvable.', 404);
        return;
    }

    json_response([
        'success' => true,
        'data' => $article,
    ]);
}

function endpoint_articles_create(): void
{
    $currentUser = auth_current_user();
    if (!is_array($currentUser) || (($currentUser['role'] ?? 'client') !== 'admin')) {
        error_response('Acces admin requis.', 403);
        return;
    }

    $payload = request_json();
    $created = repo_create_article($payload);
    cache_clear_all_data();

    json_response([
        'success' => true,
        'data' => $created,
    ], 201);
}

function endpoint_article_update(int $articleId): void
{
    $currentUser = auth_current_user();
    if (!is_array($currentUser) || (($currentUser['role'] ?? 'client') !== 'admin')) {
        error_response('Acces admin requis.', 403);
        return;
    }

    if ($articleId <= 0) {
        error_response('ID article invalide.', 422);
        return;
    }

    $payload = request_json();
    $updated = repo_update_article($articleId, $payload);
    cache_clear_all_data();

    json_response([
        'success' => true,
        'data' => $updated,
    ]);
}

function endpoint_article_delete(int $articleId): void
{
    $currentUser = auth_current_user();
    if (!is_array($currentUser) || (($currentUser['role'] ?? 'client') !== 'admin')) {
        error_response('Acces admin requis.', 403);
        return;
    }

    if ($articleId <= 0) {
        error_response('ID article invalide.', 422);
        return;
    }

    $deleted = repo_delete_article($articleId);
    cache_clear_all_data();

    json_response([
        'success' => true,
        'data' => $deleted,
    ]);
}

function endpoint_image_upload(): void
{
    $currentUser = auth_current_user();
    if (!is_array($currentUser) || (($currentUser['role'] ?? 'client') !== 'admin')) {
        error_response('Acces admin requis.', 403);
        return;
    }

    if (!isset($_FILES['image']) || !is_array($_FILES['image'])) {
        error_response('Aucun fichier image recu.', 422);
        return;
    }

    $file = $_FILES['image'];
    $error = (int) ($file['error'] ?? UPLOAD_ERR_NO_FILE);
    if ($error !== UPLOAD_ERR_OK) {
        error_response('Upload image invalide.', 422);
        return;
    }

    $tmpPath = (string) ($file['tmp_name'] ?? '');
    if ($tmpPath === '' || !is_uploaded_file($tmpPath)) {
        error_response('Fichier temporaire invalide.', 422);
        return;
    }

    $size = (int) ($file['size'] ?? 0);
    if ($size <= 0 || $size > (8 * 1024 * 1024)) {
        error_response('Image trop lourde (max 8 Mo).', 422);
        return;
    }

    $mime = '';
    if (function_exists('finfo_open')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        if ($finfo !== false) {
            $mime = (string) finfo_file($finfo, $tmpPath);
            finfo_close($finfo);
        }
    }
    if ($mime === '' && function_exists('mime_content_type')) {
        $mime = (string) mime_content_type($tmpPath);
    }

    $allowed = [
        'image/jpeg' => 'jpg',
        'image/png' => 'png',
        'image/webp' => 'webp',
        'image/gif' => 'gif',
    ];
    if (!isset($allowed[$mime])) {
        error_response('Format image non supporte.', 422);
        return;
    }

    $sku = strtoupper(trim((string) ($_POST['sku'] ?? '')));
    $prefix = validate_reference($sku) ? $sku : 'ARTICLE';
    $random = bin2hex(random_bytes(4));
    $filename = $prefix . '-' . date('YmdHis') . '-' . $random . '.' . $allowed[$mime];

    $relativeDir = 'img/products';
    $targetDir = base_path($relativeDir);
    ensure_dir($targetDir);
    $targetPath = $targetDir . DIRECTORY_SEPARATOR . $filename;

    if (!move_uploaded_file($tmpPath, $targetPath)) {
        error_response('Impossible de sauvegarder le fichier image.', 500);
        return;
    }

    $apiPath = api_base_path();
    $staticBase = str_ends_with($apiPath, '/api') ? substr($apiPath, 0, -4) : '';
    $relativeUrl = ($staticBase !== '' ? $staticBase : '') . '/img/products/' . rawurlencode($filename);
    $scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
    $host = trim((string) ($_SERVER['HTTP_HOST'] ?? 'localhost'));
    $absoluteUrl = $scheme . '://' . $host . $relativeUrl;

    json_response([
        'success' => true,
        'data' => [
            'url' => $absoluteUrl,
            'path' => $relativeUrl,
        ],
    ], 201);
}

function endpoint_marques(): void
{
    $ttl = (int) config('app.cache_ttl_marques', 300);
    $payload = cache_remember('api:marques', $ttl, static fn (): array => repo_list_marques());

    json_response([
        'success' => true,
        'data' => $payload,
    ]);
}

function endpoint_marques_create(): void
{
    $currentUser = auth_current_user();
    if (!is_array($currentUser) || (($currentUser['role'] ?? 'client') !== 'admin')) {
        error_response('Acces admin requis.', 403);
        return;
    }

    $payload = request_json();
    $created = repo_create_marque($payload);
    cache_clear_all_data();

    json_response([
        'success' => true,
        'data' => $created,
    ], 201);
}

function endpoint_modeles(): void
{
    $marqueId = query_int('marque_id', 0, 0);
    $cacheKey = 'api:modeles:' . $marqueId;
    $ttl = (int) config('app.cache_ttl_modeles', 300);

    $payload = cache_remember(
        $cacheKey,
        $ttl,
        static fn (): array => repo_list_modeles($marqueId > 0 ? $marqueId : null)
    );

    json_response([
        'success' => true,
        'data' => $payload,
    ]);
}

function endpoint_modeles_create(): void
{
    $currentUser = auth_current_user();
    if (!is_array($currentUser) || (($currentUser['role'] ?? 'client') !== 'admin')) {
        error_response('Acces admin requis.', 403);
        return;
    }

    $payload = request_json();
    $created = repo_create_modele($payload);
    cache_clear_all_data();

    json_response([
        'success' => true,
        'data' => $created,
    ], 201);
}

function endpoint_rib_get(): void
{
    $payload = rib_get();
    json_response([
        'success' => true,
        'data' => $payload,
    ]);
}

function endpoint_rib_update(): void
{
    $currentUser = auth_current_user();
    if (!is_array($currentUser) || (($currentUser['role'] ?? 'client') !== 'admin')) {
        error_response('Acces admin requis.', 403);
        return;
    }

    $payload = request_json();
    $updated = rib_upsert($payload);

    json_response([
        'success' => true,
        'data' => $updated,
    ]);
}

function endpoint_auth_register(): void
{
    $payload = request_json();
    $result = auth_register($payload);
    $user = is_array($result['user'] ?? null) ? $result['user'] : null;
    $message = trim((string) ($result['message'] ?? ''));
    $notifications = is_array($result['notifications'] ?? null) ? $result['notifications'] : null;

    json_response([
        'success' => true,
        'data' => [
            'user' => $user,
            'message' => $message,
            'notifications' => $notifications,
        ],
    ], 201);
}

function endpoint_auth_login(): void
{
    $payload = request_json();
    $user = auth_login($payload);

    json_response([
        'success' => true,
        'data' => [
            'user' => $user,
        ],
    ]);
}

function endpoint_auth_forgot(): void
{
    $payload = request_json();
    $result = auth_forgot_password($payload);

    json_response([
        'success' => true,
        'data' => $result,
    ]);
}

function endpoint_auth_logout(): void
{
    auth_logout();

    json_response([
        'success' => true,
        'data' => [
            'logged_out' => true,
        ],
    ]);
}

function endpoint_auth_me(): void
{
    json_response([
        'success' => true,
        'data' => [
            'user' => auth_current_user(),
        ],
    ]);
}

function endpoint_auth_accounts(): void
{
    $currentUser = auth_current_user();
    if (!is_array($currentUser) || (($currentUser['role'] ?? 'client') !== 'admin')) {
        error_response('Acces admin requis.', 403);
        return;
    }

    $accounts = auth_list_accounts();
    json_response([
        'success' => true,
        'data' => $accounts,
    ]);
}

function endpoint_auth_account_approval(string $accountId): void
{
    $currentUser = auth_current_user();
    if (!is_array($currentUser) || (($currentUser['role'] ?? 'client') !== 'admin')) {
        error_response('Acces admin requis.', 403);
        return;
    }

    $payload = request_json();
    $decision = trim((string) ($payload['decision'] ?? $payload['status'] ?? ''));
    if ($decision === '') {
        error_response('Decision de validation requise.', 422);
        return;
    }

    $normalizedAccountId = ctype_digit($accountId) ? (int) $accountId : $accountId;
    $updated = auth_update_account_approval($normalizedAccountId, $decision);

    json_response([
        'success' => true,
        'data' => $updated,
    ]);
}

function endpoint_cart_add(): void
{
    $limit = rate_limit_check(
        'cart_add:' . client_ip(),
        (int) config('app.rate_limit_cart_per_minute', 60),
        60
    );
    send_rate_limit_headers($limit);

    if (!$limit['allowed']) {
        header('Retry-After: ' . (string) $limit['retry_after']);
        error_response('Trop de requetes panier.', 429);
        return;
    }

    $payload = request_json();
    $articleId = (int) ($payload['article_id'] ?? 0);
    $qty = (int) ($payload['qty'] ?? 0);

    $cart = cart_add($articleId, $qty);

    json_response([
        'success' => true,
        'data' => $cart,
    ], 201);
}

function endpoint_cart_get(): void
{
    json_response([
        'success' => true,
        'data' => cart_get(),
    ]);
}

function endpoint_cart_sync(): void
{
    $limit = rate_limit_check(
        'cart_sync:' . client_ip(),
        (int) config('app.rate_limit_cart_per_minute', 60),
        60
    );
    send_rate_limit_headers($limit);

    if (!$limit['allowed']) {
        header('Retry-After: ' . (string) $limit['retry_after']);
        error_response('Trop de requetes panier.', 429);
        return;
    }

    $payload = request_json();
    $lines = $payload['lines'] ?? $payload['lignes'] ?? [];
    if (!is_array($lines)) {
        error_response('Le champ lines est invalide.', 422);
        return;
    }

    $cart = cart_sync($lines);

    json_response([
        'success' => true,
        'data' => $cart,
    ]);
}

function endpoint_order_create(): void
{
    $limit = rate_limit_check(
        'order_create:' . client_ip(),
        (int) config('app.rate_limit_order_per_minute', 20),
        60
    );
    send_rate_limit_headers($limit);

    if (!$limit['allowed']) {
        header('Retry-After: ' . (string) $limit['retry_after']);
        error_response('Trop de requetes commande.', 429);
        return;
    }

    $payload = request_json();
    $currentUser = auth_current_user();
    if (is_array($currentUser)) {
        if (!isset($payload['utilisateur']) || !is_array($payload['utilisateur'])) {
            $payload['utilisateur'] = [];
        }

        if (empty($payload['utilisateur']['id']) && isset($currentUser['id'])) {
            $payload['utilisateur']['id'] = $currentUser['id'];
        }
        if (empty($payload['utilisateur']['mail']) && isset($currentUser['mail'])) {
            $payload['utilisateur']['mail'] = $currentUser['mail'];
        }
        if (empty($payload['utilisateur']['nom']) && isset($currentUser['nom'])) {
            $payload['utilisateur']['nom'] = $currentUser['nom'];
        }
    }

    $order = order_create($payload);
    $notifications = send_order_notification_emails($order, $payload);
    $lowStockAlert = send_low_stock_alert_emails($order);
    $notifications['low_stock_sent'] = (bool) ($lowStockAlert['sent'] ?? false);
    $notifications['low_stock_items'] = is_array($lowStockAlert['items'] ?? null)
        ? $lowStockAlert['items']
        : [];

    json_response([
        'success' => true,
        'data' => $order,
        'notifications' => $notifications,
    ], 201);
}

function endpoint_stripe_checkout(): void
{
    $limit = rate_limit_check(
        'stripe_checkout:' . client_ip(),
        (int) config('app.rate_limit_order_per_minute', 20),
        60
    );
    send_rate_limit_headers($limit);

    if (!$limit['allowed']) {
        header('Retry-After: ' . (string) $limit['retry_after']);
        error_response('Trop de requetes paiement.', 429);
        return;
    }

    $currentUser = auth_current_user();
    if (!is_array($currentUser)) {
        error_response('Connexion requise.', 401);
        return;
    }

    $payload = request_json();
    $session = stripe_create_checkout_session($payload, $currentUser);

    json_response([
        'success' => true,
        'data' => $session,
    ], 201);
}

function endpoint_stripe_confirm(): void
{
    $currentUser = auth_current_user();
    if (!is_array($currentUser)) {
        error_response('Connexion requise.', 401);
        return;
    }

    $payload = request_json();
    $sessionId = trim((string) ($payload['session_id'] ?? $payload['id'] ?? ''));
    if ($sessionId === '') {
        error_response('session_id Stripe requis.', 422);
        return;
    }

    $result = stripe_confirm_checkout_for_user($sessionId, $currentUser);

    json_response([
        'success' => true,
        'data' => $result,
    ]);
}

function endpoint_stripe_webhook(): void
{
    $rawBody = file_get_contents('php://input');
    if ($rawBody === false || trim($rawBody) === '') {
        error_response('Webhook Stripe vide.', 400);
        return;
    }

    $signature = trim((string) ($_SERVER['HTTP_STRIPE_SIGNATURE'] ?? ''));
    $event = stripe_parse_webhook_event($rawBody, $signature);
    $result = stripe_handle_webhook_event($event);

    json_response([
        'success' => true,
        'data' => $result,
    ]);
}

function endpoint_orders_mine(): void
{
    $currentUser = auth_current_user();
    if (!is_array($currentUser)) {
        error_response('Connexion requise.', 401);
        return;
    }

    $rawUserId = $currentUser['id'] ?? '';
    $userId = is_numeric((string) $rawUserId) ? (int) $rawUserId : (string) $rawUserId;
    $email = trim((string) ($currentUser['mail'] ?? ''));

    $orders = order_list_for_user($userId, $email);

    json_response([
        'success' => true,
        'data' => $orders,
    ]);
}

function endpoint_admin_orders(): void
{
    $currentUser = auth_current_user();
    if (!is_array($currentUser) || (($currentUser['role'] ?? 'client') !== 'admin')) {
        error_response('Acces admin requis.', 403);
        return;
    }

    $orders = order_list_all();
    json_response([
        'success' => true,
        'data' => $orders,
    ]);
}

function endpoint_order_status_update(string $orderId): void
{
    $currentUser = auth_current_user();
    if (!is_array($currentUser) || (($currentUser['role'] ?? 'client') !== 'admin')) {
        error_response('Acces admin requis.', 403);
        return;
    }

    $payload = request_json();
    $status = trim((string) ($payload['status'] ?? ''));
    if ($status === '') {
        error_response('Statut commande requis.', 422);
        return;
    }

    $normalizedOrderId = ctype_digit($orderId) ? (int) $orderId : $orderId;
    $updated = order_update_status($normalizedOrderId, $status);

    json_response([
        'success' => true,
        'data' => $updated,
    ]);
}
