<?php
declare(strict_types=1);

function process_post_only_or_redirect(string $redirectPath): void
{
    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        return;
    }

    redirect($redirectPath);
}

function process_order_redirect_path(?int $orderId, string $page = 'job_details.php', string $fallback = '../pages/dashboard.php'): string
{
    $orderId = (int) $orderId;
    if ($orderId <= 0) {
        return $fallback;
    }

    $normalizedPage = ltrim(str_replace('\\', '/', trim($page)), '/');
    $separator = str_contains($normalizedPage, '?') ? '&' : '?';

    return '../pages/' . $normalizedPage . $separator . 'id=' . $orderId;
}

function process_safe_return_path(string $returnTo, string $fallback = ''): string
{
    $safeReturn = safe_page_return($returnTo, '');
    if ($safeReturn === '') {
        return $fallback;
    }

    return '../pages/' . $safeReturn;
}

function process_load_order_context(mysqli $conn, int $orderId, array $extraColumns = array()): ?array
{
    if ($orderId <= 0) {
        return null;
    }

    $columns = array(
        'o.order_id',
        'o.customer_id',
        'o.car_id',
        'o.bill_number',
        'o.branch_name',
        'o.status',
        'o.payment_status',
        'o.total_price',
    );

    foreach ($extraColumns as $column) {
        $column = trim((string) $column);
        if ($column !== '') {
            $columns[] = $column;
        }
    }

    $stmt = db_prepare($conn, "
        SELECT
            " . implode(",\n            ", $columns) . "
        FROM orders o
        WHERE o.order_id = ?
        LIMIT 1
    ");
    $stmt->bind_param('i', $orderId);
    $stmt->execute();
    $order = $stmt->get_result()->fetch_assoc() ?: null;
    $stmt->close();

    if (!$order) {
        return null;
    }

    $order['paid_amount'] = order_paid_amount($conn, $orderId);

    return $order;
}

function process_load_order_context_or_redirect(
    mysqli $conn,
    int $orderId,
    string $missingRedirectPath,
    string|array $missingMessage,
    array $options = array()
): array {
    $order = process_load_order_context($conn, $orderId, (array) ($options['extra_columns'] ?? array()));

    if (!$order) {
        redirect_with_flash($missingRedirectPath, 'error', $missingMessage);
    }

    if (($options['check_branch_access'] ?? true) !== false) {
        $branchRedirectPath = (string) ($options['branch_redirect_path'] ?? $missingRedirectPath);
        $branchMessage = $options['branch_message'] ?? localized_flash_message(
            'คุณไม่มีสิทธิ์เข้าถึงสาขานี้',
            'You do not have access to this branch.'
        );
        process_ensure_branch_access_or_redirect($conn, (string) ($order['branch_name'] ?? ''), $branchRedirectPath, $branchMessage);
    }

    return $order;
}

function process_ensure_permission_or_redirect(
    mysqli $conn,
    string $permission,
    string $redirectPath,
    string|array $message
): void {
    if (can_access($conn, $permission)) {
        return;
    }

    redirect_with_flash($redirectPath, 'error', $message);
}

function process_ensure_branch_access_or_redirect(
    mysqli $conn,
    ?string $branchName,
    string $redirectPath,
    string|array $message
): void {
    if (auth_can_access_branch($conn, $branchName)) {
        return;
    }

    redirect_with_flash($redirectPath, 'error', $message);
}

function process_order_balance_amount(array $order): float
{
    return max(0.0, (float) ($order['total_price'] ?? 0) - (float) ($order['paid_amount'] ?? 0));
}

function process_order_is_locked(array $order): bool
{
    $status = (string) ($order['status'] ?? '');
    $paymentStatus = (string) ($order['payment_status'] ?? '');
    $totalPrice = (float) ($order['total_price'] ?? 0);
    $balanceAmount = process_order_balance_amount($order);

    return $status === 'done'
        || $status === 'cancelled'
        || $paymentStatus === 'paid'
        || ($totalPrice > 0.0 && $balanceAmount <= 0.0);
}

function process_ensure_order_editable_or_redirect(
    array $order,
    string $redirectPath,
    string|array|null $message = null
): void {
    if (!process_order_is_locked($order)) {
        return;
    }

    $message = $message ?? localized_flash_message(
        'ข้อมูลบิลถูกล็อกแล้ว',
        'Bill data is locked.'
    );

    redirect_with_flash($redirectPath, 'error', $message);
}

function process_resolve_exception_message(
    Throwable $exception,
    string|array $fallbackMessage,
    bool $allowRawMessage = false
): string|array {
    $message = trim($exception->getMessage());
    if ($message === '') {
        return $fallbackMessage;
    }

    if (str_starts_with($message, '__CCW_FLASH__')) {
        return normalize_flash_message_payload($message);
    }

    return $allowRawMessage
        ? normalize_flash_message_payload($message)
        : $fallbackMessage;
}

function process_handle_exception_and_redirect(
    mysqli $conn,
    Throwable $exception,
    string $operation,
    string $redirectPath,
    string|array $fallbackMessage,
    array $context = array(),
    array $oldInput = array(),
    bool $allowRawMessage = false,
    ?callable $cleanup = null
): void {
    try {
        $conn->rollback();
    } catch (Throwable $rollbackException) {
    }

    log_process_failure($operation, $exception, $context);

    if (is_callable($cleanup)) {
        try {
            $cleanup();
        } catch (Throwable $cleanupException) {
            log_process_failure($operation . '_cleanup', $cleanupException, $context);
        }
    }

    redirect_with_flash(
        $redirectPath,
        'error',
        process_resolve_exception_message($exception, $fallbackMessage, $allowRawMessage),
        $oldInput
    );
}
