<?php
declare(strict_types=1);

require_once __DIR__ . '/../config/bootstrap.php';

require_login($conn);
process_post_only_or_redirect('../pages/queue.php');

ensure_order_cancellation_columns($conn);
ensure_order_source_column($conn);

$orderId = filter_input(INPUT_POST, 'order_id', FILTER_VALIDATE_INT);
$cancellationReason = trim((string) ($_POST['cancellation_reason'] ?? ''));
$returnTo = trim((string) ($_POST['return_to'] ?? ''));
$returnPath = process_safe_return_path($returnTo);
$cancelPath = '../pages/cancel_bill.php?id=' . (int) $orderId . ($returnTo !== '' ? '&return_to=' . urlencode($returnTo) : '');
$oldInput = array(
    'cancellation_reason' => $cancellationReason,
    'return_to' => $returnTo,
);

ensure_post_csrf_or_redirect('cancel_bill', $orderId ? $cancelPath : '../pages/queue.php', $oldInput);

if (!$orderId) {
    redirect_with_flash(
        '../pages/queue.php',
        'error',
        localized_flash_message('ไม่พบบิลที่ต้องการยกเลิก', 'Invalid bill target.')
    );
}

ensure_submission_token_or_redirect('cancel_bill_' . $orderId, $cancelPath, $oldInput);

if ($cancellationReason === '') {
    redirect_with_flash(
        $cancelPath,
        'error',
        localized_flash_message('กรุณาระบุเหตุผลในการยกเลิกบิล', 'Cancellation reason is required.'),
        $oldInput
    );
}

$currentUser = auth_current_user($conn);
$cancelledByEmployeeId = (int) ($currentUser['employee_id'] ?? 0);

$conn->begin_transaction();

try {
    $order = process_load_order_context_or_redirect(
        $conn,
        $orderId,
        '../pages/queue.php',
        localized_flash_message('ไม่พบบิล', 'Order not found.'),
        array(
            'extra_columns' => array('o.order_source'),
            'branch_redirect_path' => '../pages/dashboard.php',
            'branch_message' => localized_flash_message('คุณไม่มีสิทธิ์เข้าถึงสาขานี้', 'Branch access denied.'),
        )
    );

    if ((string) ($order['status'] ?? '') === 'cancelled') {
        throw new RuntimeException(localized_flash_message_string('บิลนี้ถูกยกเลิกไปแล้ว', 'Order already cancelled.'));
    }

    $balance = process_order_balance_amount($order);
    $orderSource = (string) ($order['order_source'] ?? 'booking');
    $isQuickServiceBill = $orderSource === 'quick_service';
    $isWaitingQueueBill = !$isQuickServiceBill && (string) ($order['status'] ?? '') === 'waiting';
    $isBillClosed = (string) ($order['status'] ?? '') === 'done'
        || (string) ($order['payment_status'] ?? '') === 'paid'
        || ((float) ($order['total_price'] ?? 0) > 0.0 && $balance <= 0.0);

    $canCancelBill = ($isBillClosed && !$isWaitingQueueBill && can_access($conn, 'queue_cancel_closed'))
        || ($isWaitingQueueBill && can_access($conn, 'queue_cancel_waiting'))
        || (!$isBillClosed && !$isWaitingQueueBill && (can_access($conn, 'queue_cancel_open') || ($isQuickServiceBill && can_access($conn, 'quick_service'))));

    if (!$canCancelBill) {
        throw new RuntimeException(localized_flash_message_string('คุณไม่มีสิทธิ์ยกเลิกบิลนี้', 'Cancel permission denied.'));
    }

    if ((string) ($order['status'] ?? '') === 'done') {
        order_reverse_loyalty_earn_if_exists(
            $conn,
            $orderId,
            $order,
            'Loyalty points reversed because bill was cancelled.'
        );
    }

    service_release_order_package_effects($conn, $orderId);

    $orderUpdateStmt = db_prepare($conn, "
        UPDATE orders
        SET status = 'cancelled',
            cancelled_at = NOW(),
            cancelled_by_employee_id = ?,
            cancellation_reason = ?
        WHERE order_id = ?
    ");
    $orderUpdateStmt->bind_param('isi', $cancelledByEmployeeId, $cancellationReason, $orderId);
    $orderUpdateStmt->execute();
    $orderUpdateStmt->close();

    $queueUpdateStmt = db_prepare($conn, "
        UPDATE queue
        SET status = 'cancelled'
        WHERE order_id = ?
    ");
    $queueUpdateStmt->bind_param('i', $orderId);
    $queueUpdateStmt->execute();
    $queueUpdateStmt->close();

    audit_log($conn, array(
        'module_key' => 'void',
        'action_key' => 'cancel',
        'entity_type' => 'order',
        'entity_id' => $orderId,
        'order_id' => $orderId,
        'customer_id' => (int) ($order['customer_id'] ?? 0),
        'car_id' => (int) ($order['car_id'] ?? 0),
        'branch_name' => (string) ($order['branch_name'] ?? ''),
        'bill_number' => (string) ($order['bill_number'] ?? ''),
        'amount' => (float) ($order['total_price'] ?? 0),
        'message' => 'Bill cancelled.',
        'before' => array(
            'order_source' => $orderSource,
            'status' => (string) ($order['status'] ?? ''),
            'payment_status' => (string) ($order['payment_status'] ?? ''),
            'total_price' => (float) ($order['total_price'] ?? 0),
            'paid_amount' => (float) ($order['paid_amount'] ?? 0),
            'balance_amount' => $balance,
        ),
        'after' => array(
            'status' => 'cancelled',
            'cancelled_by_employee_id' => $cancelledByEmployeeId,
            'cancellation_reason' => $cancellationReason,
        ),
        'meta' => array(
            'order_source' => $orderSource,
        ),
    ));

    $conn->commit();

    $defaultReturnPath = $orderSource === 'quick_service'
        ? '../pages/quick_service.php'
        : process_order_redirect_path($orderId);

    redirect_with_flash(
        $returnPath !== '' ? $returnPath : $defaultReturnPath,
        'success',
        localized_flash_message('ยกเลิกบิลเรียบร้อยแล้ว', 'Bill cancelled.')
    );
} catch (Throwable $exception) {
    process_handle_exception_and_redirect(
        $conn,
        $exception,
        'cancel_bill',
        $cancelPath,
        localized_flash_message('ยกเลิกบิลไม่สำเร็จ', 'Bill was not cancelled.'),
        array(
            'order_id' => $orderId,
            'return_to' => $returnTo,
            'has_reason' => $cancellationReason !== '' ? 1 : 0,
        ),
        $oldInput
    );
}
