<?php
require_once __DIR__ . '/../../includes/bootstrap.php';
require_login();

require_once __DIR__ . '/pos_recipe_deduction.php';

$pageTitle = 'Mobile POS';

if (!function_exists('h')) {
    function h($value): string { return htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8'); }
}
if (!function_exists('money_fmt')) {
    function money_fmt($amount): string { return number_format((float)$amount, 2); }
}
if (!function_exists('pos_table_exists')) {
    function pos_table_exists(PDO $pdo, string $tableName): bool {
        $stmt = $pdo->prepare("SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = :table_name");
        $stmt->execute([':table_name' => $tableName]);
        return (int)$stmt->fetchColumn() > 0;
    }
}
if (!function_exists('pos_column_exists')) {
    function pos_column_exists(PDO $pdo, string $tableName, string $columnName): bool {
        $stmt = $pdo->prepare("SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = :table_name AND column_name = :column_name");
        $stmt->execute([':table_name' => $tableName, ':column_name' => $columnName]);
        return (int)$stmt->fetchColumn() > 0;
    }
}
if (!function_exists('pos_flash')) {
    function pos_flash(string $type, string $message): void {
        $_SESSION['pos_flash'][] = ['type' => $type, 'message' => $message];
    }
}
if (!function_exists('pos_get_flash')) {
    function pos_get_flash(): array {
        $items = $_SESSION['pos_flash'] ?? [];
        unset($_SESSION['pos_flash']);
        return $items;
    }
}
if (!function_exists('pos_insert_flexible')) {
    function pos_insert_flexible(PDO $pdo, string $table, array $data): int {
        $cols = [];
        $marks = [];
        $params = [];

        foreach ($data as $col => $val) {
            if (pos_column_exists($pdo, $table, $col)) {
                $cols[] = "`$col`";
                $marks[] = ':' . $col;
                $params[':' . $col] = $val;
            }
        }

        if (!$cols) throw new RuntimeException("No matching columns found for {$table} insert.");

        $stmt = $pdo->prepare("INSERT INTO `$table` (" . implode(',', $cols) . ") VALUES (" . implode(',', $marks) . ")");
        $stmt->execute($params);
        return (int)$pdo->lastInsertId();
    }
}
if (!function_exists('pos_order_no')) {
    function pos_order_no(PDO $pdo): string {
        $prefix = 'POS-' . date('ymd') . '-';
        $stmt = $pdo->prepare("SELECT COUNT(*) FROM pos_orders WHERE pos_no LIKE :p");
        $stmt->execute([':p' => $prefix . '%']);
        return $prefix . str_pad((string)((int)$stmt->fetchColumn() + 1), 4, '0', STR_PAD_LEFT);
    }
}
if (!function_exists('pos_next_folio_no_for_property')) {
    function pos_next_folio_no_for_property(PDO $pdo, int $propertyId = 0, string $prefixType = 'FOL'): string {
        do {
            $prefix = $prefixType;
            if ($propertyId > 0 && pos_table_exists($pdo, 'properties')) {
                $stmt = $pdo->prepare("SELECT code FROM properties WHERE id = :id LIMIT 1");
                $stmt->execute([':id' => $propertyId]);
                $code = trim((string)($stmt->fetchColumn() ?: ''));
                if ($code !== '') $prefix = $prefixType . '-' . strtoupper($code);
            }

            $folioNo = $prefix . '-' . date('YmdHis') . '-' . random_int(100, 999);
            $stmt = $pdo->prepare("SELECT COUNT(*) FROM folios WHERE folio_no = :folio_no");
            $stmt->execute([':folio_no' => $folioNo]);
            $exists = (int)$stmt->fetchColumn() > 0;
        } while ($exists);

        return $folioNo;
    }
}

if (!function_exists('pos_get_order_summary')) {
    function pos_get_order_summary(PDO $pdo, int $orderId): array {
        $stmt = $pdo->prepare("
            SELECT
                o.*,
                TRIM(CONCAT(COALESCE(g.firstname,''), ' ', COALESCE(g.lastname,''))) AS guest_name
            FROM orders o
            LEFT JOIN guests g ON g.id = o.guest_id
            WHERE o.id = :id
            LIMIT 1
        ");
        $stmt->execute([':id' => $orderId]);
        $order = $stmt->fetch(PDO::FETCH_ASSOC);
        if (!$order) throw new RuntimeException('Selected reservation was not found.');
        return $order;
    }
}

if (!function_exists('pos_get_or_create_master_folio')) {
    function pos_get_or_create_master_folio(PDO $pdo, int $orderId): int {
        if (!pos_table_exists($pdo, 'folios')) return 0;

        if (pos_column_exists($pdo, 'folios', 'folio_type')) {
            $stmt = $pdo->prepare("SELECT id FROM folios WHERE order_id = :order_id AND folio_type = 'master' LIMIT 1");
            $stmt->execute([':order_id' => $orderId]);
            $folioId = (int)($stmt->fetchColumn() ?: 0);
            if ($folioId > 0) return $folioId;
        }

        $stmt = $pdo->prepare("SELECT id FROM folios WHERE order_id = :order_id ORDER BY id ASC LIMIT 1");
        $stmt->execute([':order_id' => $orderId]);
        $folioId = (int)($stmt->fetchColumn() ?: 0);
        if ($folioId > 0) return $folioId;

        $order = pos_get_order_summary($pdo, $orderId);
        $propertyId = (int)($order['property_id'] ?? 0);
        $orderNo = trim((string)($order['order_no'] ?? ''));
        $guestName = trim((string)($order['guest_name'] ?? ''));
        if ($guestName === '') $guestName = 'Guest';

        return pos_insert_flexible($pdo, 'folios', [
            'property_id' => $propertyId,
            'order_id' => $orderId,
            'folio_no' => 'FOL-M-' . $orderId,
            'folio_name' => 'Master Folio - ' . ($orderNo !== '' ? $orderNo : ('Booking #' . $orderId)) . ' - ' . $guestName,
            'folio_type' => 'master',
            'status' => 1,
            'total_charges' => 0,
            'total_payments' => 0,
            'balance' => 0,
            'created_at' => date('Y-m-d H:i:s'),
            'updated_at' => date('Y-m-d H:i:s'),
        ]);
    }
}

if (!function_exists('pos_get_room_folios')) {
    function pos_get_room_folios(PDO $pdo, int $orderId): array {
        if ($orderId <= 0 || !pos_table_exists($pdo, 'order_rooming')) return [];

        $stmt = $pdo->prepare("
            SELECT
                orm.id AS rooming_id,
                orm.room_id,
                orm.room_type_id,
                NULLIF(TRIM(CAST(orm.room_no AS CHAR)), '') AS room_no,
                rt.title AS room_type,
                TRIM(CONCAT(COALESCE(g.firstname,''), ' ', COALESCE(g.lastname,''))) AS guest
            FROM order_rooming orm
            LEFT JOIN rooms r ON r.id = orm.room_id
            LEFT JOIN room_types rt ON rt.id = orm.room_type_id
            LEFT JOIN orders o ON o.id = orm.order_id
            LEFT JOIN guests g ON g.id = o.guest_id
            WHERE orm.order_id = :order_id
              AND COALESCE(orm.checked_out_status,0) = 0
            ORDER BY orm.room_no, orm.id ASC
        ");
        $stmt->execute([':order_id' => $orderId]);
        $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

        if (!$rows) {
            $stmt = $pdo->prepare("
                SELECT
                    orm.id AS rooming_id,
                    orm.room_id,
                    orm.room_type_id,
                    NULLIF(TRIM(CAST(orm.room_no AS CHAR)), '') AS room_no,
                    rt.title AS room_type,
                    TRIM(CONCAT(COALESCE(g.firstname,''), ' ', COALESCE(g.lastname,''))) AS guest
                FROM order_rooming orm
                LEFT JOIN rooms r ON r.id = orm.room_id
                LEFT JOIN room_types rt ON rt.id = orm.room_type_id
                LEFT JOIN orders o ON o.id = orm.order_id
                LEFT JOIN guests g ON g.id = o.guest_id
                WHERE orm.order_id = :order_id
                ORDER BY orm.room_no, orm.id ASC
            ");
            $stmt->execute([':order_id' => $orderId]);
            $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
        }

        return $rows ?: [];
    }
}

if (!function_exists('pos_get_or_create_room_folio')) {
    function pos_get_or_create_room_folio(PDO $pdo, int $orderId, array $rooming): int {
        if (!pos_table_exists($pdo, 'folios')) return 0;

        $roomingId = (int)($rooming['rooming_id'] ?? 0);
        if ($roomingId <= 0) throw new RuntimeException('Invalid room folio target.');

        if (pos_column_exists($pdo, 'folios', 'rooming_id') && pos_column_exists($pdo, 'folios', 'folio_type')) {
            $stmt = $pdo->prepare("
                SELECT id
                FROM folios
                WHERE order_id = :order_id
                  AND rooming_id = :rooming_id
                  AND folio_type = 'room'
                LIMIT 1
            ");
            $stmt->execute([':order_id' => $orderId, ':rooming_id' => $roomingId]);
            $folioId = (int)($stmt->fetchColumn() ?: 0);
            if ($folioId > 0) return $folioId;
        }

        $order = pos_get_order_summary($pdo, $orderId);
        $propertyId = (int)($order['property_id'] ?? 0);
        $orderNo = trim((string)($order['order_no'] ?? ''));
        $roomNo = trim((string)($rooming['room_no'] ?? ''));
        $roomType = trim((string)($rooming['room_type'] ?? ''));
        $guest = trim((string)($rooming['guest'] ?? $order['guest_name'] ?? ''));
        if ($roomNo === '') $roomNo = 'N/A';
        if ($guest === '') $guest = 'Guest';

        $folioName = 'Room ' . $roomNo;
        if ($roomType !== '') $folioName .= ' • ' . $roomType;
        $folioName .= ' - ' . $guest;

        return pos_insert_flexible($pdo, 'folios', [
            'property_id' => $propertyId,
            'order_id' => $orderId,
            'folio_no' => 'FOL-R-' . preg_replace('/[^A-Za-z0-9_-]+/', '', $roomNo) . '-' . $orderId,
            'folio_name' => $folioName,
            'folio_type' => 'room',
            'room_id' => (int)($rooming['room_id'] ?? 0),
            'rooming_id' => $roomingId,
            'status' => 1,
            'total_charges' => 0,
            'total_payments' => 0,
            'balance' => 0,
            'created_at' => date('Y-m-d H:i:s'),
            'updated_at' => date('Y-m-d H:i:s'),
        ]);
    }
}

if (!function_exists('pos_get_guest_folios')) {
    function pos_get_guest_folios(PDO $pdo, int $orderId, int $roomingId = 0): array {
        if ($orderId <= 0 || !pos_table_exists($pdo, 'folios')) return [];
        if (!pos_column_exists($pdo, 'folios', 'folio_type')) return [];

        $whereRooming = '';
        $params = [':order_id' => $orderId];
        if ($roomingId > 0 && pos_column_exists($pdo, 'folios', 'rooming_id')) {
            $whereRooming = ' AND f.rooming_id = :rooming_id ';
            $params[':rooming_id'] = $roomingId;
        }

        $selectOccupantId = pos_column_exists($pdo, 'folios', 'occupant_id') ? 'f.occupant_id' : 'NULL AS occupant_id';
        $selectOccupantName = pos_column_exists($pdo, 'folios', 'occupant_name') ? 'f.occupant_name' : 'NULL AS occupant_name';
        $selectRoomingId = pos_column_exists($pdo, 'folios', 'rooming_id') ? 'f.rooming_id' : 'NULL AS rooming_id';
        $selectRoomId = pos_column_exists($pdo, 'folios', 'room_id') ? 'f.room_id' : 'NULL AS room_id';

        $roomJoin = '';
        $roomNoExpr = "'' AS room_no";
        if (pos_column_exists($pdo, 'folios', 'rooming_id') && pos_table_exists($pdo, 'order_rooming')) {
            $roomJoin = ' LEFT JOIN order_rooming orm ON orm.id = f.rooming_id ';
            if (pos_column_exists($pdo, 'order_rooming', 'room_no')) {
                $roomNoExpr = "NULLIF(TRIM(CAST(orm.room_no AS CHAR)), '') AS room_no";
            }
        }

        $stmt = $pdo->prepare("
            SELECT
                f.id AS folio_id,
                {$selectRoomingId},
                {$selectRoomId},
                {$selectOccupantId},
                {$selectOccupantName},
                f.folio_no,
                f.folio_name,
                {$roomNoExpr}
            FROM folios f
            {$roomJoin}
            WHERE f.order_id = :order_id
              AND f.folio_type = 'guest'
              AND COALESCE(f.status,1) = 1
              {$whereRooming}
            ORDER BY f.rooming_id ASC, f.id ASC
        ");
        $stmt->execute($params);
        return $stmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
    }
}

if (!function_exists('pos_get_or_create_guest_folio')) {
    function pos_get_or_create_guest_folio(PDO $pdo, int $orderId, array $guestTarget): int {
        if (!pos_table_exists($pdo, 'folios')) return 0;

        $folioId = (int)($guestTarget['folio_id'] ?? 0);
        if ($folioId > 0) {
            $stmt = $pdo->prepare("SELECT id FROM folios WHERE id = :id AND order_id = :order_id AND folio_type = 'guest' LIMIT 1");
            $stmt->execute([':id' => $folioId, ':order_id' => $orderId]);
            $validId = (int)($stmt->fetchColumn() ?: 0);
            if ($validId > 0) return $validId;
        }

        $occupantId = (int)($guestTarget['occupant_id'] ?? 0);
        if ($occupantId > 0 && pos_column_exists($pdo, 'folios', 'occupant_id')) {
            $stmt = $pdo->prepare("SELECT id FROM folios WHERE order_id = :order_id AND folio_type = 'guest' AND occupant_id = :occupant_id LIMIT 1");
            $stmt->execute([':order_id' => $orderId, ':occupant_id' => $occupantId]);
            $foundId = (int)($stmt->fetchColumn() ?: 0);
            if ($foundId > 0) return $foundId;
        }

        throw new RuntimeException('Selected guest folio was not found. Please complete check-in again for this room.');
    }
}

if (!function_exists('pos_get_charge_folio_id')) {
    function pos_get_charge_folio_id(PDO $pdo, int $orderId, string $postTo): array {
        if ($postTo === '' || $postTo === 'master') {
            return [
                'folio_id' => pos_get_or_create_master_folio($pdo, $orderId),
                'scope' => 'master',
                'rooming_id' => null,
                'occupant_id' => null,
                'guest_name' => pos_guest_name_for_order($pdo, $orderId),
                'room_label' => pos_room_label_for_order($pdo, $orderId),
            ];
        }

        $target = json_decode($postTo, true);
        if (!is_array($target)) throw new RuntimeException('Invalid folio selection.');

        $targetType = strtolower(trim((string)($target['target_type'] ?? $target['folio_type'] ?? $target['type'] ?? 'room')));

        if ($targetType === 'guest') {
            $folioId = pos_get_or_create_guest_folio($pdo, $orderId, $target);
            $roomNo = trim((string)($target['room_no'] ?? ''));
            $guestName = trim((string)($target['occupant_name'] ?? $target['guest'] ?? $target['folio_name'] ?? 'Guest'));
            return [
                'folio_id' => $folioId,
                'scope' => 'guest',
                'rooming_id' => !empty($target['rooming_id']) ? (int)$target['rooming_id'] : null,
                'occupant_id' => !empty($target['occupant_id']) ? (int)$target['occupant_id'] : null,
                'guest_name' => $guestName,
                'room_label' => $roomNo !== '' ? $roomNo : pos_room_label_for_order($pdo, $orderId),
            ];
        }

        $roomNo = trim((string)($target['room_no'] ?? ''));
        return [
            'folio_id' => pos_get_or_create_room_folio($pdo, $orderId, $target),
            'scope' => 'room',
            'rooming_id' => (int)($target['rooming_id'] ?? 0),
            'occupant_id' => null,
            'guest_name' => trim((string)($target['guest'] ?? pos_guest_name_for_order($pdo, $orderId))),
            'room_label' => $roomNo !== '' ? $roomNo : pos_room_label_for_order($pdo, $orderId),
        ];
    }
}
if (!function_exists('pos_recalculate_folio_totals')) {
    function pos_recalculate_folio_totals(PDO $pdo, int $folioId): void {
        if ($folioId <= 0 || !pos_table_exists($pdo, 'folio_transactions')) return;

        $stmt = $pdo->prepare("
            SELECT
                COALESCE(SUM(debit), 0) AS total_debits,
                COALESCE(SUM(credit), 0) AS total_credits
            FROM folio_transactions
            WHERE folio_id = :folio_id
        ");
        $stmt->execute([':folio_id' => $folioId]);
        $totals = $stmt->fetch(PDO::FETCH_ASSOC);

        $charges = (float)($totals['total_debits'] ?? 0);
        $payments = (float)($totals['total_credits'] ?? 0);
        $balance = $charges - $payments;

        if (pos_table_exists($pdo, 'folios')) {
            $updates = [];
            $params = [':id' => $folioId];
            if (pos_column_exists($pdo, 'folios', 'total_charges')) { $updates[] = "total_charges = :total_charges"; $params[':total_charges'] = round($charges, 2); }
            if (pos_column_exists($pdo, 'folios', 'total_payments')) { $updates[] = "total_payments = :total_payments"; $params[':total_payments'] = round($payments, 2); }
            if (pos_column_exists($pdo, 'folios', 'balance')) { $updates[] = "balance = :balance"; $params[':balance'] = round($balance, 2); }
            if (pos_column_exists($pdo, 'folios', 'updated_at')) $updates[] = "updated_at = NOW()";
            if ($updates) {
                $stmt = $pdo->prepare("UPDATE folios SET " . implode(', ', $updates) . " WHERE id = :id");
                $stmt->execute($params);
            }
        }
    }
}

if (!function_exists('pos_sync_order_payment_status')) {
    function pos_sync_order_payment_status(PDO $pdo, int $orderId): void {
        if ($orderId <= 0 || !pos_table_exists($pdo, 'folios') || !pos_column_exists($pdo, 'orders', 'payment_status')) return;

        $stmt = $pdo->prepare("
            SELECT
                COALESCE(SUM(total_payments),0) AS total_payments,
                COALESCE(SUM(balance),0) AS total_balance
            FROM folios
            WHERE order_id = :order_id
        ");
        $stmt->execute([':order_id' => $orderId]);
        $row = $stmt->fetch(PDO::FETCH_ASSOC);

        $payments = (float)($row['total_payments'] ?? 0);
        $balance = (float)($row['total_balance'] ?? 0);

        if ($payments <= 0.00001) $status = 0;
        elseif ($balance <= 0.00001) $status = 2;
        else $status = 1;

        $stmt = $pdo->prepare("UPDATE orders SET payment_status = :status WHERE id = :id");
        $stmt->execute([':status' => $status, ':id' => $orderId]);
    }
}

if (!function_exists('pos_find_or_create_folio')) {
    function pos_find_or_create_folio(PDO $pdo, int $orderId): int {
        return pos_get_or_create_master_folio($pdo, $orderId);
    }
}

if (!function_exists('pos_post_folio_charge')) {
    function pos_post_folio_charge(PDO $pdo, int $folioId, int $orderId, int $posOrderId, string $description, float $amount): int {
        if (!pos_table_exists($pdo, 'folio_transactions')) return 0;

        $propertyId = 0;
        if (pos_table_exists($pdo, 'orders') && pos_column_exists($pdo, 'orders', 'property_id')) {
            $stmt = $pdo->prepare("SELECT property_id FROM orders WHERE id = :id LIMIT 1");
            $stmt->execute([':id' => $orderId]);
            $propertyId = (int)($stmt->fetchColumn() ?: 0);
        }

        $txId = pos_insert_flexible($pdo, 'folio_transactions', [
            'property_id' => $propertyId,
            'folio_id' => $folioId,
            'order_id' => $orderId,
            'tx_date' => date('Y-m-d H:i:s'),
            'transaction_date' => date('Y-m-d'),
            'date' => date('Y-m-d'),
            'tx_type' => 'pos',
            'type' => 'charge',
            'transaction_type' => 'charge',
            'source_table' => 'pos_orders',
            'source_id' => $posOrderId,
            'source' => 'pos',
            'description' => $description,
            'amount' => $amount,
            'debit' => $amount,
            'credit' => 0,
            'created_at' => date('Y-m-d H:i:s'),
            'updated_at' => date('Y-m-d H:i:s'),
        ]);

        pos_recalculate_folio_totals($pdo, $folioId);
        pos_sync_order_payment_status($pdo, $orderId);

        return $txId;
    }
}

if (!function_exists('pos_stock_balance')) {
    function pos_stock_balance(PDO $pdo, int $itemId, int $storeId): float {
        $stmt = $pdo->prepare("SELECT COALESCE(SUM(qty_in - qty_out),0) FROM stock_movements WHERE item_id = :item_id AND store_id = :store_id");
        $stmt->execute([':item_id' => $itemId, ':store_id' => $storeId]);
        return (float)$stmt->fetchColumn();
    }
}
if (!function_exists('pos_item_has_recipe')) {
    function pos_item_has_recipe(PDO $pdo, int $itemId): bool {
        if (!pos_table_exists($pdo, 'inventory_recipes')) return false;
        $stmt = $pdo->prepare("SELECT COUNT(*) FROM inventory_recipes WHERE recipe_item_id = :item_id AND is_active = 1");
        $stmt->execute([':item_id' => $itemId]);
        return (int)$stmt->fetchColumn() > 0;
    }
}

if (!function_exists('pos_guest_name_for_order')) {
    function pos_guest_name_for_order(PDO $pdo, int $orderId): string {
        if ($orderId <= 0 || !pos_table_exists($pdo, 'orders')) return '';

        try {
            if (pos_column_exists($pdo, 'orders', 'guest_id') && pos_table_exists($pdo, 'guests')) {
                $stmt = $pdo->prepare("
                    SELECT TRIM(CONCAT(COALESCE(g.firstname,''), ' ', COALESCE(g.lastname,''))) AS guest_name
                    FROM orders o
                    LEFT JOIN guests g ON g.id = o.guest_id
                    WHERE o.id = :id
                    LIMIT 1
                ");
                $stmt->execute([':id' => $orderId]);
                $guestName = trim((string)($stmt->fetchColumn() ?: ''));
                if ($guestName !== '') return $guestName;
            }

            foreach (['guest_name','pax_name','customer_name','client_name'] as $col) {
                if (pos_column_exists($pdo, 'orders', $col)) {
                    $stmt = $pdo->prepare("SELECT `{$col}` FROM orders WHERE id = :id LIMIT 1");
                    $stmt->execute([':id' => $orderId]);
                    $guestName = trim((string)($stmt->fetchColumn() ?: ''));
                    if ($guestName !== '') return $guestName;
                }
            }
        } catch (Throwable $e) {}

        return 'Reservation #' . $orderId;
    }
}


if (!function_exists('pos_room_label_for_order')) {
    function pos_room_label_for_order(PDO $pdo, int $orderId): string {
        if ($orderId <= 0) return '';

        /*
         * CONFIRMED PMS STRUCTURE:
         *   order_rooming.order_id = orders.id
         *   order_rooming.room_no  = actual room number
         *   order_rooming.room_id  = optional link to rooms.id
         *
         * This direct lookup is intentionally FIRST so POS does not depend on
         * order_rooming_guests or guessed fallback tables.
         */
        try {
            if (pos_table_exists($pdo, 'order_rooming') && pos_column_exists($pdo, 'order_rooming', 'order_id') && pos_column_exists($pdo, 'order_rooming', 'room_no')) {
                $roomExpr = "NULLIF(TRIM(CAST(orm.room_no AS CHAR)), '')";
                $join = '';

                if (pos_column_exists($pdo, 'order_rooming', 'room_id') && pos_table_exists($pdo, 'rooms')) {
                    foreach (['room_no','room_number','room_name','name','room'] as $candidate) {
                        if (pos_column_exists($pdo, 'rooms', $candidate)) {
                            $join = " LEFT JOIN rooms r ON r.id = orm.room_id ";
                            $roomExpr = "COALESCE(NULLIF(TRIM(CAST(r.`{$candidate}` AS CHAR)), ''), NULLIF(TRIM(CAST(orm.room_no AS CHAR)), ''))";
                            break;
                        }
                    }
                }

                $whereStatus = '';
                if (pos_column_exists($pdo, 'order_rooming', 'checked_out_status')) {
                    $whereStatus = " AND COALESCE(orm.checked_out_status,0) = 0 ";
                }

                $stmt = $pdo->prepare("
                    SELECT GROUP_CONCAT(DISTINCT {$roomExpr} ORDER BY {$roomExpr} SEPARATOR ', ') AS rooms
                    FROM order_rooming orm
                    {$join}
                    WHERE orm.order_id = :order_id
                    {$whereStatus}
                ");
                $stmt->execute([':order_id' => $orderId]);
                $roomText = trim((string)($stmt->fetchColumn() ?: ''));

                if ($roomText === '' && $whereStatus !== '') {
                    $stmt = $pdo->prepare("
                        SELECT GROUP_CONCAT(DISTINCT {$roomExpr} ORDER BY {$roomExpr} SEPARATOR ', ') AS rooms
                        FROM order_rooming orm
                        {$join}
                        WHERE orm.order_id = :order_id
                    ");
                    $stmt->execute([':order_id' => $orderId]);
                    $roomText = trim((string)($stmt->fetchColumn() ?: ''));
                }

                if ($roomText !== '') return $roomText;
            }
        } catch (Throwable $e) {}

        $cleanLabels = function(array $labels): string {
            $out = [];
            foreach ($labels as $label) {
                $label = trim((string)$label);
                if ($label === '' || strtolower($label) === 'null') continue;
                $out[$label] = true;
            }
            return implode(', ', array_keys($out));
        };

        $roomLabelExpression = function(string $alias, string $table) use ($pdo): string {
            $candidates = ['room_no','room_number','room_label','room_name','name','room','number','code'];
            foreach ($candidates as $col) {
                if (pos_column_exists($pdo, $table, $col)) {
                    return "NULLIF(TRIM(CAST({$alias}.`{$col}` AS CHAR)), '')";
                }
            }
            return "NULL";
        };

        /*
         * Your PMS stores checked-in guest rows in order_rooming_guests.
         * That table does not hold the room number directly. It links by:
         *   order_rooming_guests.order_id  -> orders.id
         *   order_rooming_guests.rooming_id -> order_rooming.id
         * Then order_rooming normally links to rooms using room_id, or stores room_no directly.
         */
        try {
            if (pos_table_exists($pdo, 'order_rooming_guests') && pos_table_exists($pdo, 'order_rooming')) {
                $joins = " INNER JOIN order_rooming org_rooming ON org_rooming.id = org.rooming_id ";
                $parts = [];

                foreach (['room_no','room_number','room_label','room_name','room'] as $col) {
                    if (pos_column_exists($pdo, 'order_rooming', $col)) {
                        $parts[] = "NULLIF(TRIM(CAST(org_rooming.`{$col}` AS CHAR)), '')";
                    }
                }

                if (pos_column_exists($pdo, 'order_rooming', 'room_id') && pos_table_exists($pdo, 'rooms')) {
                    $roomExpr = $roomLabelExpression('r', 'rooms');
                    $joins .= " LEFT JOIN rooms r ON r.id = org_rooming.room_id ";
                    $parts[] = $roomExpr;
                    $parts[] = "CONCAT('Room ', org_rooming.room_id)";
                }

                if ($parts) {
                    $labelExpr = 'COALESCE(' . implode(', ', $parts) . ')';
                    $checkedInFilter = '';
                    if (pos_column_exists($pdo, 'order_rooming_guests', 'checked_in_at')) {
                        $checkedInFilter = " AND org.checked_in_at IS NOT NULL ";
                    }

                    $stmt = $pdo->prepare("\n                        SELECT GROUP_CONCAT(DISTINCT {$labelExpr} ORDER BY {$labelExpr} SEPARATOR ', ') AS rooms\n                        FROM order_rooming_guests org\n                        {$joins}\n                        WHERE org.order_id = :order_id\n                        {$checkedInFilter}\n                    ");
                    $stmt->execute([':order_id' => $orderId]);
                    $roomText = trim((string)($stmt->fetchColumn() ?: ''));

                    if ($roomText === '' && $checkedInFilter !== '') {
                        $stmt = $pdo->prepare("\n                            SELECT GROUP_CONCAT(DISTINCT {$labelExpr} ORDER BY {$labelExpr} SEPARATOR ', ') AS rooms\n                            FROM order_rooming_guests org\n                            {$joins}\n                            WHERE org.order_id = :order_id\n                        ");
                        $stmt->execute([':order_id' => $orderId]);
                        $roomText = trim((string)($stmt->fetchColumn() ?: ''));
                    }

                    if ($roomText !== '') return $roomText;
                }
            }
        } catch (Throwable $e) {}

        try {
            if (pos_table_exists($pdo, 'order_rooming')) {
                $roomingAlias = 'orm';
                $join = '';
                $parts = [];

                foreach (['room_no','room_number','room_label','room_name','room'] as $col) {
                    if (pos_column_exists($pdo, 'order_rooming', $col)) {
                        $parts[] = "NULLIF(TRIM(CAST({$roomingAlias}.`{$col}` AS CHAR)), '')";
                    }
                }

                if (pos_column_exists($pdo, 'order_rooming', 'room_id') && pos_table_exists($pdo, 'rooms')) {
                    $roomExpr = $roomLabelExpression('r', 'rooms');
                    $join = " LEFT JOIN rooms r ON r.id = {$roomingAlias}.room_id ";
                    $parts[] = $roomExpr;
                    $parts[] = "CONCAT('Room ', {$roomingAlias}.room_id)";
                }

                if ($parts) {
                    $labelExpr = 'COALESCE(' . implode(', ', $parts) . ')';
                    $orderFilter = pos_column_exists($pdo, 'order_rooming', 'order_id') ? "{$roomingAlias}.order_id" : (pos_column_exists($pdo, 'order_rooming', 'reservation_id') ? "{$roomingAlias}.reservation_id" : '');
                    if ($orderFilter !== '') {
                        $stmt = $pdo->prepare("\n                            SELECT GROUP_CONCAT(DISTINCT {$labelExpr} ORDER BY {$labelExpr} SEPARATOR ', ') AS rooms\n                            FROM order_rooming {$roomingAlias}\n                            {$join}\n                            WHERE {$orderFilter} = :order_id\n                        ");
                        $stmt->execute([':order_id' => $orderId]);
                        $roomText = trim((string)($stmt->fetchColumn() ?: ''));
                        if ($roomText !== '') return $roomText;
                    }
                }
            }
        } catch (Throwable $e) {}

        try {
            if (pos_table_exists($pdo, 'orders')) {
                foreach (['room_no','room_number','room_label','room','room_name'] as $col) {
                    if (pos_column_exists($pdo, 'orders', $col)) {
                        $stmt = $pdo->prepare("SELECT `{$col}` FROM orders WHERE id = :id LIMIT 1");
                        $stmt->execute([':id' => $orderId]);
                        $value = trim((string)($stmt->fetchColumn() ?: ''));
                        if ($value !== '') return $value;
                    }
                }
            }
        } catch (Throwable $e) {}

        return '';
    }
}



/* ===========================
   POS PRINTER ROUTING HELPERS
   Creates print jobs for kitchen/bar/icecream/master printers.
   Actual silent printing requires a local print agent/service that reads pos_print_jobs.
=========================== */
if (!function_exists('pos_get_item_printer')) {
    function pos_get_item_printer(PDO $pdo, array $item): ?array {
        if (!pos_table_exists($pdo, 'pos_printers')) return null;
        if (!pos_column_exists($pdo, 'inventory_items', 'default_pos_printer_id')) return null;
        $printerId = (int)($item['default_pos_printer_id'] ?? 0);
        if ($printerId <= 0) return null;
        $stmt = $pdo->prepare("SELECT * FROM pos_printers WHERE id = :id AND is_active = 1 LIMIT 1");
        $stmt->execute([':id' => $printerId]);
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        return $row ?: null;
    }
}

if (!function_exists('pos_get_master_printer')) {
    function pos_get_master_printer(PDO $pdo): ?array {
        if (!pos_table_exists($pdo, 'pos_printers')) return null;
        $stmt = $pdo->query("SELECT * FROM pos_printers WHERE is_active = 1 AND is_master_printer = 1 ORDER BY id ASC LIMIT 1");
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        if ($row) return $row;
        $stmt = $pdo->query("SELECT * FROM pos_printers WHERE is_active = 1 AND printer_role = 'master' ORDER BY id ASC LIMIT 1");
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        return $row ?: null;
    }
}

if (!function_exists('pos_make_print_payload')) {
    function pos_make_print_payload(array $header, array $lines, string $title): string {
        $out = [];
        $out[] = str_repeat('=', 34);
        $out[] = strtoupper($title);
        $out[] = str_repeat('=', 34);
        $out[] = 'Order: ' . ($header['pos_no'] ?? '');
        $out[] = 'Store: ' . ($header['store_name'] ?? '');
        $out[] = 'Date : ' . date('Y-m-d H:i:s');
        if (!empty($header['guest_name'])) $out[] = 'Guest: ' . $header['guest_name'];
        if (!empty($header['room_label'])) $out[] = 'Room : ' . $header['room_label'];
        if (!empty($header['target_label'])) $out[] = 'Post : ' . $header['target_label'];
        if (!empty($header['notes'])) $out[] = 'Notes: ' . $header['notes'];
        $out[] = str_repeat('-', 34);
        foreach ($lines as $line) {
            $out[] = money_fmt($line['qty']) . ' x ' . $line['item_name'];
            if (!empty($line['note'])) $out[] = '  Note: ' . $line['note'];
        }
        $out[] = str_repeat('-', 34);
        $out[] = 'TOTAL ITEMS: ' . count($lines);
        $out[] = str_repeat('=', 34);
        return implode("\n", $out) . "\n\n";
    }
}

if (!function_exists('pos_create_print_job')) {
    function pos_create_print_job(PDO $pdo, int $posOrderId, ?int $printerId, string $printType, string $payload, ?string $printerName = null): int {
        if (!pos_table_exists($pdo, 'pos_print_jobs')) return 0;
        return pos_insert_flexible($pdo, 'pos_print_jobs', [
            'pos_order_id' => $posOrderId,
            'printer_id' => $printerId,
            'printer_name' => $printerName,
            'print_type' => $printType,
            'payload_text' => $payload,
            'status' => 'pending',
            'copies' => 1,
            'created_at' => date('Y-m-d H:i:s'),
            'updated_at' => date('Y-m-d H:i:s'),
        ]);
    }
}

$errors = [];

try {
    $pdo->exec("CREATE TABLE IF NOT EXISTS inventory_item_categories (
        id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        category_name VARCHAR(120) NOT NULL,
        category_type ENUM('stock','food','bar','curio','consumable','service','other') NOT NULL DEFAULT 'stock',
        is_active TINYINT(1) NOT NULL DEFAULT 1,
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        UNIQUE KEY uq_inventory_category_name (category_name)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    // POS must use the same subcategory table created by Inventory Items.
    // The correct table is inventory_item_subcategories (plural).
    // A previous draft used inventory_item_subcategory (singular), so we also migrate any rows from that table.
    $pdo->exec("CREATE TABLE IF NOT EXISTS inventory_item_subcategories (
        id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        category_id INT UNSIGNED NOT NULL,
        subcategory_name VARCHAR(160) NOT NULL,
        is_active TINYINT(1) NOT NULL DEFAULT 1,
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        UNIQUE KEY uq_inventory_subcategory_category_name (category_id, subcategory_name),
        INDEX idx_inventory_subcategory_category (category_id),
        INDEX idx_inventory_subcategory_active (is_active)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    if (pos_table_exists($pdo, 'inventory_item_subcategory')) {
        $pdo->exec("INSERT IGNORE INTO inventory_item_subcategories (category_id, subcategory_name, is_active, created_at, updated_at)
            SELECT category_id, subcategory_name, is_active, created_at, updated_at
            FROM inventory_item_subcategory");
    }

    $pdo->exec("CREATE TABLE IF NOT EXISTS inventory_units (
        id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        unit_code VARCHAR(30) NOT NULL,
        unit_name VARCHAR(80) NOT NULL,
        is_active TINYINT(1) NOT NULL DEFAULT 1,
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        UNIQUE KEY uq_inventory_unit_code (unit_code)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    $pdo->exec("CREATE TABLE IF NOT EXISTS inventory_items (
        id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        item_code VARCHAR(60) NULL,
        item_name VARCHAR(180) NOT NULL,
        category_id INT UNSIGNED NULL,
        unit_id INT UNSIGNED NULL,
        item_type ENUM('stock','food','bar','curio','consumable','service','recipe','other') NOT NULL DEFAULT 'stock',
        barcode VARCHAR(100) NULL,
        description TEXT NULL,
        cost_price DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        avg_cost DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        selling_price DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        tax_rate DECIMAL(7,4) NOT NULL DEFAULT 0.0000,
        reorder_level DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        reorder_qty DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        is_stock_item TINYINT(1) NOT NULL DEFAULT 1,
        is_pos_item TINYINT(1) NOT NULL DEFAULT 0,
        allow_room_charge TINYINT(1) NOT NULL DEFAULT 1,
        track_expiry TINYINT(1) NOT NULL DEFAULT 0,
        is_active TINYINT(1) NOT NULL DEFAULT 1,
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        UNIQUE KEY uq_inventory_item_code (item_code),
        INDEX idx_inventory_item_name (item_name),
        INDEX idx_inventory_item_pos (is_pos_item)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    $pdo->exec("CREATE TABLE IF NOT EXISTS store_locations (
        id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        location_code VARCHAR(50) NULL,
        location_name VARCHAR(150) NOT NULL,
        location_type ENUM('main_store','bar','restaurant','curio','kitchen','housekeeping','maintenance','other') NOT NULL DEFAULT 'main_store',
        is_pos_location TINYINT(1) NOT NULL DEFAULT 0,
        allow_room_charge TINYINT(1) NOT NULL DEFAULT 1,
        is_active TINYINT(1) NOT NULL DEFAULT 1,
        notes TEXT NULL,
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        UNIQUE KEY uq_store_location_code (location_code),
        INDEX idx_store_location_active (is_active)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");



    $pdo->exec("CREATE TABLE IF NOT EXISTS pos_printers (
        id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        printer_name VARCHAR(120) NOT NULL,
        printer_role ENUM('kitchen','bar','icecream','master','other') NOT NULL DEFAULT 'kitchen',
        connection_type ENUM('windows_share','network_ip','browser','agent_queue','other') NOT NULL DEFAULT 'agent_queue',
        printer_path VARCHAR(255) NULL,
        printer_ip VARCHAR(80) NULL,
        printer_port INT UNSIGNED NULL DEFAULT 9100,
        is_master_printer TINYINT(1) NOT NULL DEFAULT 0,
        is_active TINYINT(1) NOT NULL DEFAULT 1,
        notes TEXT NULL,
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        INDEX idx_pos_printer_active (is_active),
        INDEX idx_pos_printer_role (printer_role)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    $pdo->exec("CREATE TABLE IF NOT EXISTS pos_print_jobs (
        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        pos_order_id BIGINT UNSIGNED NOT NULL,
        printer_id INT UNSIGNED NULL,
        printer_name VARCHAR(120) NULL,
        print_type ENUM('master','station','reprint','void') NOT NULL DEFAULT 'station',
        payload_text MEDIUMTEXT NOT NULL,
        status ENUM('pending','printing','printed','failed','cancelled') NOT NULL DEFAULT 'pending',
        copies INT UNSIGNED NOT NULL DEFAULT 1,
        attempts INT UNSIGNED NOT NULL DEFAULT 0,
        last_error TEXT NULL,
        printed_at DATETIME NULL,
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        INDEX idx_print_jobs_order (pos_order_id),
        INDEX idx_print_jobs_printer (printer_id),
        INDEX idx_print_jobs_status (status)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    if (pos_table_exists($pdo, 'inventory_items') && !pos_column_exists($pdo, 'inventory_items', 'default_pos_printer_id')) {
        $pdo->exec("ALTER TABLE inventory_items ADD COLUMN default_pos_printer_id INT UNSIGNED NULL AFTER subcategory_id");
    }

    if (pos_table_exists($pdo, 'inventory_items') && !pos_column_exists($pdo, 'inventory_items', 'subcategory_id')) {
        $pdo->exec("ALTER TABLE inventory_items ADD COLUMN subcategory_id INT UNSIGNED NULL AFTER category_id");
    }

    $colCheck = $pdo->prepare("SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name='store_locations' AND column_name=:col");
    foreach ([
        'allow_room_charge' => "ALTER TABLE store_locations ADD COLUMN allow_room_charge TINYINT(1) NOT NULL DEFAULT 1 AFTER is_pos_location",
        'notes' => "ALTER TABLE store_locations ADD COLUMN notes TEXT NULL AFTER is_active"
    ] as $col => $sql) {
        $colCheck->execute([':col' => $col]);
        if ((int)$colCheck->fetchColumn() === 0) $pdo->exec($sql);
    }

    $pdo->exec("CREATE TABLE IF NOT EXISTS stock_movements (
        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        item_id INT UNSIGNED NOT NULL,
        store_id INT UNSIGNED NOT NULL,
        movement_type ENUM('OPENING','GRN','ISSUE','SALE','TRANSFER_IN','TRANSFER_OUT','ADJUSTMENT_IN','ADJUSTMENT_OUT','WASTAGE','RETURN') NOT NULL,
        qty_in DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        qty_out DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        unit_cost DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        total_cost DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        reference_type VARCHAR(60) NULL,
        reference_id BIGINT UNSIGNED NULL,
        notes TEXT NULL,
        movement_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        INDEX idx_stock_item_store (item_id, store_id),
        INDEX idx_stock_movement_date (movement_date),
        INDEX idx_stock_reference (reference_type, reference_id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    $pdo->exec("CREATE TABLE IF NOT EXISTS pos_orders (
        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        pos_no VARCHAR(60) NOT NULL,
        store_id INT UNSIGNED NOT NULL,
        order_id INT UNSIGNED NULL,
        folio_id INT UNSIGNED NULL,
        guest_name VARCHAR(180) NULL,
        room_label VARCHAR(80) NULL,
        charge_scope VARCHAR(30) NULL,
        rooming_id INT UNSIGNED NULL,
        occupant_id INT UNSIGNED NULL,
        target_label VARCHAR(220) NULL,
        sale_type ENUM('cash','card','transfer','room_charge','complimentary','void') NOT NULL DEFAULT 'cash',
        payment_method VARCHAR(40) NULL,
        subtotal DECIMAL(14,2) NOT NULL DEFAULT 0.00,
        tax_amount DECIMAL(14,2) NOT NULL DEFAULT 0.00,
        discount_amount DECIMAL(14,2) NOT NULL DEFAULT 0.00,
        total_amount DECIMAL(14,2) NOT NULL DEFAULT 0.00,
        status ENUM('open','paid','charged_to_room','void') NOT NULL DEFAULT 'open',
        notes TEXT NULL,
        created_by INT UNSIGNED NULL,
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        UNIQUE KEY uq_pos_no (pos_no),
        INDEX idx_pos_store (store_id),
        INDEX idx_pos_order (order_id),
        INDEX idx_pos_status (status),
        INDEX idx_pos_created (created_at)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    $pdo->exec("CREATE TABLE IF NOT EXISTS pos_order_items (
        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        pos_order_id BIGINT UNSIGNED NOT NULL,
        item_id INT UNSIGNED NOT NULL,
        item_name VARCHAR(180) NOT NULL,
        qty DECIMAL(14,4) NOT NULL DEFAULT 1.0000,
        unit_price DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        unit_cost DECIMAL(14,4) NOT NULL DEFAULT 0.0000,
        tax_rate DECIMAL(7,4) NOT NULL DEFAULT 0.0000,
        prep_printer_id INT UNSIGNED NULL,
        prep_printer_name VARCHAR(120) NULL,
        line_total DECIMAL(14,2) NOT NULL DEFAULT 0.00,
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        INDEX idx_pos_item_order (pos_order_id),
        INDEX idx_pos_item_item (item_id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");


    if (pos_table_exists($pdo, 'pos_orders')) {
        $posOrderAlterCols = [
            'charge_scope' => "ALTER TABLE pos_orders ADD COLUMN charge_scope VARCHAR(30) NULL AFTER room_label",
            'rooming_id' => "ALTER TABLE pos_orders ADD COLUMN rooming_id INT UNSIGNED NULL AFTER charge_scope",
            'occupant_id' => "ALTER TABLE pos_orders ADD COLUMN occupant_id INT UNSIGNED NULL AFTER rooming_id",
            'target_label' => "ALTER TABLE pos_orders ADD COLUMN target_label VARCHAR(220) NULL AFTER occupant_id",
        ];
        foreach ($posOrderAlterCols as $col => $sql) {
            if (!pos_column_exists($pdo, 'pos_orders', $col)) $pdo->exec($sql);
        }
    }


    if (pos_table_exists($pdo, 'pos_order_items')) {
        $posItemAlterCols = [
            'prep_printer_id' => "ALTER TABLE pos_order_items ADD COLUMN prep_printer_id INT UNSIGNED NULL AFTER tax_rate",
            'prep_printer_name' => "ALTER TABLE pos_order_items ADD COLUMN prep_printer_name VARCHAR(120) NULL AFTER prep_printer_id",
        ];
        foreach ($posItemAlterCols as $col => $sql) {
            if (!pos_column_exists($pdo, 'pos_order_items', $col)) $pdo->exec($sql);
        }
    }

    pos_recipe_prepare_tables($pdo);

} catch (Throwable $e) {
    $errors[] = 'Could not prepare POS tables: ' . $e->getMessage();
}

$storeId = (int)($_GET['store_id'] ?? $_POST['store_id'] ?? 0);
$selectedStore = null;

try {
    if ($storeId <= 0) {
        $stmt = $pdo->query("SELECT id FROM store_locations WHERE is_active=1 AND is_pos_location=1 ORDER BY location_type ASC, location_name ASC LIMIT 1");
        $storeId = (int)($stmt->fetchColumn() ?: 0);
    }

    if ($storeId > 0) {
        $stmt = $pdo->prepare("SELECT * FROM store_locations WHERE id=:id LIMIT 1");
        $stmt->execute([':id' => $storeId]);
        $selectedStore = $stmt->fetch(PDO::FETCH_ASSOC) ?: null;
    }
} catch (Throwable $e) {
    $errors[] = 'Could not load POS store: ' . $e->getMessage();
}

if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST') {
    try {
        if (function_exists('verify_csrf')) verify_csrf();

        $action = (string)($_POST['action'] ?? '');

        if ($action === 'complete_sale') {
            if (!$selectedStore) throw new RuntimeException('Please select a valid POS store.');
            if ((int)$selectedStore['is_pos_location'] !== 1) throw new RuntimeException('Selected store is not enabled for POS.');

            $cartJson = (string)($_POST['cart_json'] ?? '[]');
            $cart = json_decode($cartJson, true);
            if (!is_array($cart) || !$cart) throw new RuntimeException('Cart is empty.');

            $paymentMethod = (string)($_POST['payment_method'] ?? 'cash');
            $allowedPayments = ['cash','card','transfer','room_charge','complimentary'];
            if (!in_array($paymentMethod, $allowedPayments, true)) $paymentMethod = 'cash';

            $orderId = (int)($_POST['order_id'] ?? 0);
            $postTo = trim((string)($_POST['post_to'] ?? 'master'));
            $notes = trim((string)($_POST['notes'] ?? ''));

            if ($paymentMethod === 'room_charge') {
                if ((int)$selectedStore['allow_room_charge'] !== 1) throw new RuntimeException('Room charging is not enabled for this POS location.');
                if ($orderId <= 0) throw new RuntimeException('Please select a checked-in reservation for room charge.');
            }

            if (!$pdo->inTransaction()) {
                $pdo->beginTransaction();
            }

            $itemsForSale = [];
            $subtotal = 0.0;
            $taxAmount = 0.0;

            foreach ($cart as $line) {
                $itemId = (int)($line['id'] ?? 0);
                $qty = max(0.0001, (float)($line['qty'] ?? 1));

                $stmt = $pdo->prepare("SELECT ii.*, u.unit_code FROM inventory_items ii LEFT JOIN inventory_units u ON u.id=ii.unit_id WHERE ii.id=:id AND ii.is_active=1 AND ii.is_pos_item=1 LIMIT 1");
                $stmt->execute([':id' => $itemId]);
                $item = $stmt->fetch(PDO::FETCH_ASSOC);

                if (!$item) throw new RuntimeException('Invalid POS item selected.');

                $hasRecipe = pos_item_has_recipe($pdo, $itemId);
                if (!$hasRecipe && (int)$item['is_stock_item'] === 1) {
                    $balance = pos_stock_balance($pdo, $itemId, $storeId);
                    if ($balance < $qty) throw new RuntimeException('Not enough stock for ' . $item['item_name'] . '. Available: ' . money_fmt($balance));
                }

                $price = (float)$item['selling_price'];
                $lineTotal = round($qty * $price, 2);
                $taxRate = (float)$item['tax_rate'];
                $lineTax = $taxRate > 0 ? round($lineTotal - ($lineTotal / (1 + ($taxRate / 100))), 2) : 0.0;

                $subtotal += $lineTotal;
                $taxAmount += $lineTax;

                $itemsForSale[] = [
                    'item' => $item,
                    'qty' => $qty,
                    'price' => $price,
                    'cost' => (float)($item['avg_cost'] ?: $item['cost_price']),
                    'tax_rate' => $taxRate,
                    'line_total' => $lineTotal,
                    'has_recipe' => $hasRecipe,
                ];
            }

            $discountAmount = 0.0;
            $totalAmount = max(0, round($subtotal - $discountAmount, 2));
            $folioId = 0;
            $guestName = null;
            $roomLabel = null;
            $chargeScope = null;
            $roomingId = null;
            $occupantId = null;
            $targetLabel = null;

            if ($paymentMethod === 'room_charge') {
                $stmt = $pdo->prepare("SELECT id FROM orders WHERE id = :id LIMIT 1");
                $stmt->execute([':id' => $orderId]);
                $reservation = $stmt->fetch(PDO::FETCH_ASSOC);
                if (!$reservation) throw new RuntimeException('Selected reservation was not found.');

                $target = pos_get_charge_folio_id($pdo, $orderId, $postTo);
                $folioId = (int)($target['folio_id'] ?? 0);
                $chargeScope = (string)($target['scope'] ?? 'master');
                $roomingId = !empty($target['rooming_id']) ? (int)$target['rooming_id'] : null;
                $occupantId = !empty($target['occupant_id']) ? (int)$target['occupant_id'] : null;

                $guestName = trim((string)($target['guest_name'] ?? ''));
                if ($guestName === '') $guestName = pos_guest_name_for_order($pdo, $orderId);
                $roomLabel = trim((string)($target['room_label'] ?? ''));
                if ($roomLabel === '') $roomLabel = pos_room_label_for_order($pdo, $orderId);
                if ($roomLabel === '') $roomLabel = 'Reservation #' . $orderId;
                $targetLabel = ucfirst($chargeScope ?: 'folio') . ': ' . ($guestName ?: 'Guest') . ' / Room ' . $roomLabel;
            }

            $posNo = pos_order_no($pdo);
            $status = $paymentMethod === 'room_charge' ? 'charged_to_room' : 'paid';

            $posOrderId = pos_insert_flexible($pdo, 'pos_orders', [
                'pos_no' => $posNo,
                'store_id' => $storeId,
                'order_id' => $orderId > 0 ? $orderId : null,
                'folio_id' => $folioId > 0 ? $folioId : null,
                'guest_name' => $guestName,
                'room_label' => $roomLabel,
                'charge_scope' => $chargeScope,
                'rooming_id' => $roomingId,
                'occupant_id' => $occupantId,
                'target_label' => $targetLabel,
                'sale_type' => $paymentMethod,
                'payment_method' => $paymentMethod,
                'subtotal' => $subtotal,
                'tax_amount' => $taxAmount,
                'discount_amount' => $discountAmount,
                'total_amount' => $totalAmount,
                'status' => $status,
                'notes' => $notes !== '' ? $notes : null,
                'created_by' => $_SESSION['user_id'] ?? null,
                'created_at' => date('Y-m-d H:i:s'),
                'updated_at' => date('Y-m-d H:i:s'),
            ]);

            $folioDescriptionParts = [];
            $masterPrintLines = [];
            $stationPrintGroups = [];

            foreach ($itemsForSale as $line) {
                $item = $line['item'];
                $qty = $line['qty'];

                $prepPrinter = pos_get_item_printer($pdo, $item);
                $prepPrinterId = $prepPrinter ? (int)$prepPrinter['id'] : null;
                $prepPrinterName = $prepPrinter ? (string)$prepPrinter['printer_name'] : null;

                pos_insert_flexible($pdo, 'pos_order_items', [
                    'pos_order_id' => $posOrderId,
                    'item_id' => (int)$item['id'],
                    'item_name' => $item['item_name'],
                    'qty' => $qty,
                    'unit_price' => $line['price'],
                    'unit_cost' => $line['cost'],
                    'tax_rate' => $line['tax_rate'],
                    'prep_printer_id' => $prepPrinterId,
                    'prep_printer_name' => $prepPrinterName,
                    'line_total' => $line['line_total'],
                    'created_at' => date('Y-m-d H:i:s'),
                ]);

                $printLine = [
                    'item_id' => (int)$item['id'],
                    'item_name' => (string)$item['item_name'],
                    'qty' => $qty,
                    'printer_id' => $prepPrinterId,
                    'printer_name' => $prepPrinterName,
                ];
                $masterPrintLines[] = $printLine;
                if ($prepPrinterId) {
                    if (!isset($stationPrintGroups[$prepPrinterId])) {
                        $stationPrintGroups[$prepPrinterId] = [
                            'printer' => $prepPrinter,
                            'lines' => [],
                        ];
                    }
                    $stationPrintGroups[$prepPrinterId]['lines'][] = $printLine;
                }

                $folioDescriptionParts[] = money_fmt($qty) . ' x ' . $item['item_name'];
            }

            $deductionResult = pos_deduct_stock_for_order($pdo, (int)$posOrderId, true);
            $deductedCount = count($deductionResult['deductions'] ?? []);

            if ($paymentMethod === 'room_charge') {
                if ($folioId <= 0) throw new RuntimeException('Could not locate/create folio for room charge.');

                $description = ($selectedStore['location_name'] ?? 'POS') . ' - ' . implode(', ', array_slice($folioDescriptionParts, 0, 5));
                if (count($folioDescriptionParts) > 5) $description .= '...';

                pos_post_folio_charge($pdo, $folioId, $orderId, $posOrderId, $description, $totalAmount);
            }

            $printHeader = [
                'pos_no' => $posNo,
                'store_name' => (string)($selectedStore['location_name'] ?? 'POS'),
                'guest_name' => $guestName,
                'room_label' => $roomLabel,
                'target_label' => $targetLabel,
                'notes' => $notes,
            ];

            foreach ($stationPrintGroups as $group) {
                $printer = $group['printer'];
                $payload = pos_make_print_payload($printHeader, $group['lines'], (string)$printer['printer_name']);
                pos_create_print_job($pdo, $posOrderId, (int)$printer['id'], 'station', $payload, (string)$printer['printer_name']);
            }

            $masterPrinter = pos_get_master_printer($pdo);
            if ($masterPrinter) {
                $payload = pos_make_print_payload($printHeader, $masterPrintLines, 'MASTER POS ORDER COPY');
                pos_create_print_job($pdo, $posOrderId, (int)$masterPrinter['id'], 'master', $payload, (string)$masterPrinter['printer_name']);
            }

            if ($pdo->inTransaction()) {
                $pdo->commit();
            }

            $stockMsg = $deductedCount > 0 ? ' Stock deducted: ' . $deductedCount . ' line(s).' : ' No stock deduction was required.';
            pos_flash('success', 'POS sale completed successfully. Receipt: ' . $posNo . '.' . $stockMsg);
            header('Location: pos.php?store_id=' . $storeId . '&receipt_id=' . $posOrderId);
            exit;
        }

    } catch (Throwable $e) {
        if ($pdo->inTransaction()) $pdo->rollBack();
        pos_flash('danger', $e->getMessage());
        header('Location: pos.php?store_id=' . $storeId);
        exit;
    }
}

$stores = [];
$categories = [];
$subcategories = [];
$items = [];
$reservations = [];
$receipt = null;
$receiptItems = [];
$receiptDeductions = [];

try {
    $stores = $pdo->query("SELECT * FROM store_locations WHERE is_active=1 ORDER BY is_pos_location DESC, location_name ASC")->fetchAll(PDO::FETCH_ASSOC);

    $categories = $pdo->query("SELECT DISTINCT c.id, c.category_name, c.category_type FROM inventory_item_categories c INNER JOIN inventory_items ii ON ii.category_id=c.id WHERE c.is_active=1 AND ii.is_active=1 AND ii.is_pos_item=1 ORDER BY c.category_type ASC, c.category_name ASC")->fetchAll(PDO::FETCH_ASSOC);

    if (pos_table_exists($pdo, 'inventory_item_subcategories')) {
        // Show the subcategory selector whenever subcategories exist.
        // Do not restrict this list to POS-linked items only, because new subcategories may exist before items are assigned.
        $subcategories = $pdo->query("
            SELECT
                sc.id,
                sc.category_id,
                sc.subcategory_name,
                c.category_name
            FROM inventory_item_subcategories sc
            LEFT JOIN inventory_item_categories c ON c.id = sc.category_id
            WHERE sc.is_active = 1
            ORDER BY c.category_name ASC, sc.subcategory_name ASC
        ")->fetchAll(PDO::FETCH_ASSOC);
    }

    if ($storeId > 0) {
        $stmt = $pdo->prepare("
            SELECT
                ii.*,
                c.category_name,
                c.category_type,
                sc.id AS pos_subcategory_id,
                sc.subcategory_name,
                u.unit_code,
                COALESCE(sb.balance_qty,0) AS stock_balance,
                CASE WHEN r.id IS NULL THEN 0 ELSE 1 END AS has_recipe
            FROM inventory_items ii
            LEFT JOIN inventory_item_categories c ON c.id=ii.category_id
            LEFT JOIN inventory_item_subcategories sc ON sc.id = ii.subcategory_id
            LEFT JOIN inventory_units u ON u.id=ii.unit_id
            LEFT JOIN (
                SELECT item_id, store_id, SUM(qty_in-qty_out) AS balance_qty
                FROM stock_movements
                WHERE store_id=:store_id
                GROUP BY item_id, store_id
            ) sb ON sb.item_id=ii.id
            LEFT JOIN inventory_recipes r ON r.recipe_item_id = ii.id AND r.is_active = 1
            WHERE ii.is_active=1
              AND ii.is_pos_item=1
            ORDER BY c.category_name ASC, sc.subcategory_name ASC, ii.item_name ASC
        ");
        $stmt->execute([':store_id' => $storeId]);
        $items = $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    if (pos_table_exists($pdo, 'orders')) {
        /*
         * CONFIRMED PMS STRUCTURE:
         *   orders.guest_id      -> guests.id
         *   order_rooming.order_id -> orders.id
         *   order_rooming.room_no  -> actual room number
         *
         * This query intentionally uses the exact tables confirmed from phpMyAdmin.
         */
        $checkInCol = pos_column_exists($pdo, 'orders', 'check_in') ? 'o.check_in' : (pos_column_exists($pdo, 'orders', 'arrival_date') ? 'o.arrival_date' : 'NULL');
        $checkOutCol = pos_column_exists($pdo, 'orders', 'check_out') ? 'o.check_out' : (pos_column_exists($pdo, 'orders', 'departure_date') ? 'o.departure_date' : 'NULL');

        $statusWhere = "";
        if (pos_column_exists($pdo, 'orders', 'status')) {
            $statusWhere = " AND LOWER(COALESCE(o.status,'')) IN ('checked_in','checkin','in_house','confirmed','reserved','open') ";
        }

        if (
            pos_table_exists($pdo, 'guests')
            && pos_column_exists($pdo, 'orders', 'guest_id')
            && pos_table_exists($pdo, 'order_rooming')
            && pos_column_exists($pdo, 'order_rooming', 'order_id')
            && pos_column_exists($pdo, 'order_rooming', 'room_no')
        ) {
            $roomingWhere = "";
            if (pos_column_exists($pdo, 'order_rooming', 'checked_out_status')) {
                $roomingWhere .= " AND COALESCE(r.checked_out_status,0) = 0 ";
            }

            $stmt = $pdo->query("
                SELECT
                    o.id,
                    TRIM(CONCAT(COALESCE(g.firstname,''), ' ', COALESCE(g.lastname,''))) AS guest_name,
                    {$checkInCol} AS check_in,
                    {$checkOutCol} AS check_out,
                    GROUP_CONCAT(DISTINCT NULLIF(TRIM(CAST(r.room_no AS CHAR)), '') ORDER BY r.room_no SEPARATOR ', ') AS room_label,
                    MAX(COALESCE(r.checked_in_status,0)) AS checked_in_status
                FROM orders o
                INNER JOIN guests g ON g.id = o.guest_id
                INNER JOIN order_rooming r ON r.order_id = o.id {$roomingWhere}
                WHERE 1=1 {$statusWhere}
                GROUP BY o.id, guest_name, check_in, check_out
                ORDER BY r.room_no ASC, o.id DESC
                LIMIT 150
            ");
            $reservations = $stmt->fetchAll(PDO::FETCH_ASSOC);

            /*
             * If no rows appear because statuses are different, fall back to the same exact joins without status filters.
             */
            if (!$reservations) {
                $stmt = $pdo->query("
                    SELECT
                        o.id,
                        TRIM(CONCAT(COALESCE(g.firstname,''), ' ', COALESCE(g.lastname,''))) AS guest_name,
                        {$checkInCol} AS check_in,
                        {$checkOutCol} AS check_out,
                        GROUP_CONCAT(DISTINCT NULLIF(TRIM(CAST(r.room_no AS CHAR)), '') ORDER BY r.room_no SEPARATOR ', ') AS room_label,
                        MAX(COALESCE(r.checked_in_status,0)) AS checked_in_status
                    FROM orders o
                    INNER JOIN guests g ON g.id = o.guest_id
                    INNER JOIN order_rooming r ON r.order_id = o.id
                    GROUP BY o.id, guest_name, check_in, check_out
                    ORDER BY r.room_no ASC, o.id DESC
                    LIMIT 150
                ");
                $reservations = $stmt->fetchAll(PDO::FETCH_ASSOC);
            }
        } else {
            /*
             * Safe fallback for older/demo schemas.
             */
            $guestExpr = pos_column_exists($pdo, 'orders', 'guest_name') ? 'o.guest_name' : (pos_column_exists($pdo, 'orders', 'pax_name') ? 'o.pax_name' : "CONCAT('Reservation #', o.id)");
            $stmt = $pdo->query("SELECT o.id, {$guestExpr} AS guest_name, {$checkInCol} AS check_in, {$checkOutCol} AS check_out, '' AS room_label FROM orders o WHERE 1=1 {$statusWhere} ORDER BY o.id DESC LIMIT 100");
            $reservations = $stmt->fetchAll(PDO::FETCH_ASSOC);
        }

        foreach ($reservations as &$res) {
            $roomLabel = trim((string)($res['room_label'] ?? ''));
            if ($roomLabel === '') $roomLabel = pos_room_label_for_order($pdo, (int)$res['id']);
            $res['room_label'] = $roomLabel !== '' ? $roomLabel : ('ROOM NOT LINKED - Reservation #' . (int)$res['id']);
            if (trim((string)($res['guest_name'] ?? '')) === '') {
                $res['guest_name'] = pos_guest_name_for_order($pdo, (int)$res['id']);
            }

            $res['room_folios'] = [];
            foreach (pos_get_room_folios($pdo, (int)$res['id']) as $rf) {
                $roomingIdForTarget = (int)($rf['rooming_id'] ?? 0);
                $guestFolios = [];
                foreach (pos_get_guest_folios($pdo, (int)$res['id'], $roomingIdForTarget) as $gf) {
                    $guestFolios[] = [
                        'target_type' => 'guest',
                        'folio_id' => (int)($gf['folio_id'] ?? 0),
                        'rooming_id' => (int)($gf['rooming_id'] ?? $roomingIdForTarget),
                        'room_id' => (int)($gf['room_id'] ?? $rf['room_id'] ?? 0),
                        'occupant_id' => (int)($gf['occupant_id'] ?? 0),
                        'room_no' => (string)($gf['room_no'] ?? $rf['room_no'] ?? ''),
                        'folio_no' => (string)($gf['folio_no'] ?? ''),
                        'folio_name' => (string)($gf['folio_name'] ?? ''),
                        'occupant_name' => (string)($gf['occupant_name'] ?? $gf['folio_name'] ?? ''),
                    ];
                }

                $res['room_folios'][] = [
                    'target_type' => 'room',
                    'rooming_id' => $roomingIdForTarget,
                    'room_id' => (int)($rf['room_id'] ?? 0),
                    'room_type_id' => (int)($rf['room_type_id'] ?? 0),
                    'room_no' => (string)($rf['room_no'] ?? ''),
                    'room_type' => (string)($rf['room_type'] ?? ''),
                    'guest' => (string)($rf['guest'] ?? $res['guest_name'] ?? ''),
                    'guest_folios' => $guestFolios,
                ];
            }
        }
        unset($res);
    }

    $receiptId = (int)($_GET['receipt_id'] ?? 0);
    if ($receiptId > 0) {
        $stmt = $pdo->prepare("SELECT po.*, sl.location_name FROM pos_orders po LEFT JOIN store_locations sl ON sl.id=po.store_id WHERE po.id=:id LIMIT 1");
        $stmt->execute([':id' => $receiptId]);
        $receipt = $stmt->fetch(PDO::FETCH_ASSOC) ?: null;

        if ($receipt) {
            $stmt = $pdo->prepare("SELECT * FROM pos_order_items WHERE pos_order_id=:id ORDER BY id ASC");
            $stmt->execute([':id' => $receiptId]);
            $receiptItems = $stmt->fetchAll(PDO::FETCH_ASSOC);

            $receiptPrintJobs = [];
            if (pos_table_exists($pdo, 'pos_print_jobs')) {
                $stmt = $pdo->prepare("SELECT * FROM pos_print_jobs WHERE pos_order_id = :id ORDER BY print_type ASC, id ASC");
                $stmt->execute([':id' => $receiptId]);
                $receiptPrintJobs = $stmt->fetchAll(PDO::FETCH_ASSOC);
            }

            if (pos_table_exists($pdo, 'pos_stock_deductions')) {
                $stmt = $pdo->prepare("
                    SELECT
                        d.*,
                        sold.item_name AS sold_item_name,
                        deducted.item_name AS deducted_item_name,
                        sl.location_name
                    FROM pos_stock_deductions d
                    LEFT JOIN inventory_items sold ON sold.id = d.sold_item_id
                    LEFT JOIN inventory_items deducted ON deducted.id = d.deducted_item_id
                    LEFT JOIN store_locations sl ON sl.id = d.store_id
                    WHERE d.pos_order_id = :id
                    ORDER BY d.id ASC
                ");
                $stmt->execute([':id' => $receiptId]);
                $receiptDeductions = $stmt->fetchAll(PDO::FETCH_ASSOC);
            }
        }
    }

} catch (Throwable $e) {
    $errors[] = 'Could not load POS data: ' . $e->getMessage();
}

$flashes = pos_get_flash();

require_once __DIR__ . '/../../includes/header.php';
?>

<div class="pos-page">
    <div class="pos-topbar">
        <div>
            <div class="page-eyebrow text-muted"><i class="bi bi-cash-register"></i> Stores &amp; POS</div>
            <h3 class="mb-0">Mobile POS</h3>
            <div class="text-muted small">Bar • Restaurant • Curio shop sales with recipe stock deduction and room charge integration</div>
        </div>
        <div class="d-flex gap-2 align-items-center flex-wrap">
            <form method="get" class="d-flex gap-2">
                <select name="store_id" class="form-select form-select-sm" onchange="this.form.submit()">
                    <?php foreach ($stores as $s): ?>
                        <option value="<?php echo (int)$s['id']; ?>" <?php echo $storeId === (int)$s['id'] ? 'selected' : ''; ?>>
                            <?php echo h($s['location_name']); ?><?php echo (int)$s['is_pos_location'] === 1 ? ' • POS' : ''; ?>
                        </option>
                    <?php endforeach; ?>
                </select>
            </form>
            <a href="/rooms/modules/pos/pos_printers.php" class="btn btn-sm btn-outline-secondary"><i class="bi bi-printer me-1"></i>Printers</a>
            <a href="/rooms/modules/inventory/recipes.php" class="btn btn-sm btn-outline-secondary"><i class="bi bi-egg-fried me-1"></i>Recipes</a>
            <a href="/rooms/modules/inventory/inventory_items.php" class="btn btn-sm btn-outline-secondary"><i class="bi bi-box-seam me-1"></i>Items</a>
            <a href="/rooms/modules/inventory/stock_movements.php" class="btn btn-sm btn-outline-secondary"><i class="bi bi-arrow-left-right me-1"></i>Movements</a>
        </div>
    </div>

    <?php foreach ($flashes as $flash): ?>
        <div class="alert alert-<?php echo h($flash['type']); ?>"><?php echo h($flash['message']); ?></div>
    <?php endforeach; ?>

    <?php if ($errors): ?>
        <div class="alert alert-danger">
            <div class="fw-bold mb-2">Please fix the following:</div>
            <ul class="mb-0"><?php foreach ($errors as $err): ?><li><?php echo h($err); ?></li><?php endforeach; ?></ul>
        </div>
    <?php endif; ?>

    <?php if (!$selectedStore): ?>
        <div class="alert alert-warning">No POS store selected. Create or enable a POS location in Store Locations.</div>
    <?php elseif ((int)$selectedStore['is_pos_location'] !== 1): ?>
        <div class="alert alert-warning">This location is not enabled as a POS location. Enable POS Location in Store Locations.</div>
    <?php endif; ?>

    <?php if ($receipt): ?>
        <div class="card panel-card mb-4 receipt-card">
            <div class="card-header d-flex justify-content-between align-items-center">
                <h5 class="mb-0">Receipt <?php echo h($receipt['pos_no']); ?></h5>
                <div class="d-flex gap-2">
                    <button class="btn btn-sm btn-outline-primary" onclick="posPrintReceiptAndReturn()"><i class="bi bi-printer me-1"></i>Print</button>
                    <a class="btn btn-sm btn-outline-secondary" href="pos.php?store_id=<?php echo (int)$storeId; ?>"><i class="bi bi-arrow-left me-1"></i>Back to POS</a>
                </div>
            </div>
            <div class="card-body">
                <div class="row g-3">
                    <div class="col-md-3"><strong>Store:</strong> <?php echo h($receipt['location_name']); ?></div>
                    <div class="col-md-3"><strong>Status:</strong> <?php echo h($receipt['status']); ?></div>
                    <div class="col-md-3"><strong>Payment:</strong> <?php echo h($receipt['payment_method']); ?></div>
                    <div class="col-md-3 text-md-end"><strong>Total:</strong> <?php echo money_fmt($receipt['total_amount']); ?></div>
                    <?php if (!empty($receipt['room_label']) || !empty($receipt['guest_name'])): ?>
                        <div class="col-md-6"><strong>Guest:</strong> <?php echo h($receipt['guest_name'] ?: ''); ?></div>
                        <div class="col-md-6 text-md-end"><strong>Room:</strong> <?php echo h($receipt['room_label'] ?: ''); ?></div>
                        <?php if (!empty($receipt['target_label'])): ?>
                            <div class="col-12"><strong>Posted To:</strong> <?php echo h($receipt['target_label']); ?></div>
                        <?php endif; ?>
                    <?php endif; ?>
                </div>

                <hr>

                <table class="table table-sm mb-0">
                    <thead><tr><th>Item</th><th class="text-end">Qty</th><th class="text-end">Price</th><th class="text-end">Total</th></tr></thead>
                    <tbody>
                    <?php foreach ($receiptItems as $ri): ?>
                        <tr>
                            <td><?php echo h($ri['item_name']); ?></td>
                            <td class="text-end"><?php echo money_fmt($ri['qty']); ?></td>
                            <td class="text-end"><?php echo money_fmt($ri['unit_price']); ?></td>
                            <td class="text-end"><?php echo money_fmt($ri['line_total']); ?></td>
                        </tr>
                    <?php endforeach; ?>
                    </tbody>
                </table>

                <?php if (!empty($receiptPrintJobs)): ?>
                    <hr>
                    <h6 class="fw-bold">Print Jobs</h6>
                    <div class="table-responsive">
                        <table class="table table-sm mb-0">
                            <thead><tr><th>Type</th><th>Printer</th><th>Status</th><th class="text-end">Copies</th></tr></thead>
                            <tbody>
                            <?php foreach ($receiptPrintJobs as $job): ?>
                                <tr>
                                    <td><?php echo h(ucwords((string)$job['print_type'])); ?></td>
                                    <td><?php echo h($job['printer_name'] ?: ('Printer #' . (int)$job['printer_id'])); ?></td>
                                    <td><span class="badge text-bg-light border"><?php echo h($job['status']); ?></span></td>
                                    <td class="text-end"><?php echo (int)($job['copies'] ?? 1); ?></td>
                                </tr>
                            <?php endforeach; ?>
                            </tbody>
                        </table>
                    </div>
                <?php endif; ?>

                <?php if ($receiptDeductions): ?>
                    <hr>
                    <h6 class="fw-bold">Stock Deducted</h6>
                    <div class="table-responsive">
                        <table class="table table-sm mb-0">
                            <thead><tr><th>Sold Item</th><th>Deducted Stock</th><th>Type</th><th>Store</th><th class="text-end">Qty</th><th class="text-end">Cost</th></tr></thead>
                            <tbody>
                            <?php foreach ($receiptDeductions as $d): ?>
                                <tr>
                                    <td><?php echo h($d['sold_item_name'] ?: 'Item'); ?></td>
                                    <td><?php echo h($d['deducted_item_name'] ?: 'Stock'); ?></td>
                                    <td><span class="badge text-bg-light border"><?php echo h(str_replace('_', ' ', $d['deduction_type'])); ?></span></td>
                                    <td><?php echo h($d['location_name'] ?: 'Store'); ?></td>
                                    <td class="text-end"><?php echo money_fmt($d['qty_deducted']); ?></td>
                                    <td class="text-end"><?php echo money_fmt($d['total_cost']); ?></td>
                                </tr>
                            <?php endforeach; ?>
                            </tbody>
                        </table>
                    </div>
                <?php endif; ?>
            </div>
        </div>
    <?php endif; ?>

    <form method="post" id="posForm">
        <?php if (function_exists('csrf_field')) echo csrf_field(); ?>
        <input type="hidden" name="action" value="complete_sale">
        <input type="hidden" name="store_id" value="<?php echo (int)$storeId; ?>">
        <input type="hidden" name="cart_json" id="cartJson" value="[]">

        <div class="pos-layout">
            <section class="pos-products">
                <div class="pos-filter-card">
                    <div class="input-group">
                        <span class="input-group-text"><i class="bi bi-search"></i></span>
                        <input type="text" id="posSearch" class="form-control" placeholder="Search item / barcode">
                    </div>
                    <div class="category-pills mt-3">
                        <button type="button" class="cat-pill active" data-cat="all">All</button>
                        <?php foreach ($categories as $cat): ?>
                            <button type="button" class="cat-pill" data-cat="<?php echo (int)$cat['id']; ?>">
                                <?php echo h($cat['category_name']); ?>
                            </button>
                        <?php endforeach; ?>
                    </div>

                    <div class="subcategory-filter-box mt-3">
                        <label class="form-label small mb-1">Subcategory</label>
                        <select id="posSubcategory" class="form-select form-select-sm">
                            <option value="all" data-cat="all">All subcategories</option>
                            <?php foreach ($subcategories as $sub): ?>
                                <option value="<?php echo (int)$sub['id']; ?>" data-cat="<?php echo (int)$sub['category_id']; ?>">
                                    <?php echo h(($sub['category_name'] ? $sub['category_name'] . ' - ' : '') . $sub['subcategory_name']); ?>
                                </option>
                            <?php endforeach; ?>
                        </select>
                        <?php if (!$subcategories): ?>
                            <div class="small text-muted mt-1">No active subcategories found yet. Add/assign subcategories from Inventory Items.</div>
                        <?php endif; ?>
                    </div>
                </div>

                <div class="product-grid" id="productGrid">
                    <?php if (!$items): ?>
                        <div class="alert alert-info">No POS items found. Mark items as “Sell on POS” in Inventory Items.</div>
                    <?php else: ?>
                        <?php foreach ($items as $item): ?>
                            <?php
                                $stockItem = (int)$item['is_stock_item'] === 1;
                                $hasRecipe = (int)($item['has_recipe'] ?? 0) === 1;
                                $outOfStock = (!$hasRecipe && $stockItem && (float)$item['stock_balance'] <= 0);
                            ?>
                            <button
                                type="button"
                                class="product-tile <?php echo $outOfStock ? 'is-disabled' : ''; ?>"
                                data-id="<?php echo (int)$item['id']; ?>"
                                data-name="<?php echo h($item['item_name']); ?>"
                                data-price="<?php echo h($item['selling_price']); ?>"
                                data-cat="<?php echo (int)$item['category_id']; ?>"
                                data-subcat="<?php echo (int)($item['pos_subcategory_id'] ?? 0); ?>"
                                data-stock="<?php echo h($item['stock_balance']); ?>"
                                data-stock-item="<?php echo (int)$item['is_stock_item']; ?>"
                                data-recipe="<?php echo $hasRecipe ? '1' : '0'; ?>"
                                data-search="<?php echo h(strtolower(($item['item_name'] ?? '') . ' ' . ($item['item_code'] ?? '') . ' ' . ($item['barcode'] ?? ''))); ?>"
                                <?php echo $outOfStock ? 'disabled' : ''; ?>
                            >
                                <span class="product-type"><?php echo h(($item['category_name'] ?: ucwords($item['item_type'])) . (!empty($item['subcategory_name']) ? ' • ' . $item['subcategory_name'] : '')); ?></span>
                                <strong><?php echo h($item['item_name']); ?></strong>
                                <span class="product-price"><?php echo money_fmt($item['selling_price']); ?></span>
                                <span class="product-stock <?php echo $outOfStock ? 'text-danger' : ''; ?>">
                                    <?php if ($hasRecipe): ?>
                                        Recipe item
                                    <?php elseif ($stockItem): ?>
                                        Stock: <?php echo money_fmt($item['stock_balance']); ?>
                                    <?php else: ?>
                                        Service/Menu
                                    <?php endif; ?>
                                </span>
                            </button>
                        <?php endforeach; ?>
                    <?php endif; ?>
                </div>
            </section>

            <aside class="pos-cart">
                <div class="cart-card">
                    <div class="cart-header">
                        <div>
                            <h5 class="mb-0">Current Sale</h5>
                            <div class="small text-muted"><?php echo h($selectedStore['location_name'] ?? 'POS Store'); ?></div>
                        </div>
                        <button type="button" class="btn btn-sm btn-outline-danger" id="clearCart"><i class="bi bi-trash"></i></button>
                    </div>

                    <div id="cartLines" class="cart-lines"><div class="empty-cart">Tap items to add to cart.</div></div>

                    <div class="cart-totals">
                        <div><span>Subtotal</span><strong id="subtotalText">0.00</strong></div>
                        <div><span>Total</span><strong id="totalText">0.00</strong></div>
                    </div>

                    <div class="mt-3">
                        <label class="form-label">Payment Method</label>
                        <select name="payment_method" id="paymentMethod" class="form-select">
                            <option value="cash">Cash</option>
                            <option value="card">Card</option>
                            <option value="transfer">Transfer</option>
                            <?php if ($selectedStore && (int)$selectedStore['allow_room_charge'] === 1): ?>
                                <option value="room_charge">Room Charge</option>
                            <?php endif; ?>
                            <option value="complimentary">Complimentary</option>
                        </select>
                    </div>

                    <div class="mt-3 room-charge-box" id="roomChargeBox" style="display:none;">
                        <label class="form-label">Reservation / Room Account</label>
                        <select name="order_id" id="roomChargeOrder" class="form-select">
                            <option value="0" data-room-folios="[]">Select reservation</option>
                            <?php foreach ($reservations as $res): ?>
                                <option
                                    value="<?php echo (int)$res['id']; ?>"
                                    data-room-folios='<?php echo h(json_encode($res['room_folios'] ?? [], JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_TAG | JSON_HEX_AMP)); ?>'
                                    data-guest="<?php echo h($res['guest_name']); ?>"
                                    data-room-label="<?php echo h($res['room_label']); ?>">
                                    Room <?php echo h($res['room_label'] ?: ('Reservation #' . (int)$res['id'])); ?> - <?php echo h($res['guest_name']); ?>
                                    <?php if (!empty($res['check_in'])): ?> (<?php echo h($res['check_in']); ?>)<?php endif; ?>
                                </option>
                            <?php endforeach; ?>
                        </select>

                        <label class="form-label mt-2">Post To Folio</label>
                        <select name="post_to" id="postToFolio" class="form-select">
                            <option value="master">Master Folio</option>
                        </select>
                        <div class="small text-muted mt-1">Choose Master Folio, Room Folio, or Individual Guest Folio created at check-in.</div>
                    </div>

                    <div class="mt-3">
                        <label class="form-label">Notes</label>
                        <textarea name="notes" class="form-control" rows="2" placeholder="Optional"></textarea>
                    </div>

                    <button type="submit" class="btn btn-primary w-100 mt-3" id="completeSaleBtn" <?php echo !$selectedStore ? 'disabled' : ''; ?>>
                        <i class="bi bi-check-circle me-2"></i>Complete Sale
                    </button>

                    <div class="small text-muted mt-3">Recipe items deduct ingredients. Normal stock items deduct themselves.</div>
                </div>
            </aside>
        </div>
    </form>
</div>

<style>
.pos-page{padding-bottom:24px}.pos-topbar{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:20px}.pos-layout{display:grid;grid-template-columns:1fr 380px;gap:20px;align-items:start}.pos-filter-card,.cart-card,.panel-card{background:#fff;border:1px solid rgba(15,23,42,.08);border-radius:22px;box-shadow:0 12px 30px rgba(15,23,42,.08)}.pos-filter-card{padding:14px;margin-bottom:14px}.category-pills{display:flex;gap:8px;flex-wrap:wrap}.cat-pill{border:1px solid #dbe3ef;background:#f8fafc;color:#334155;border-radius:999px;padding:7px 12px;font-weight:800;font-size:12px}.cat-pill.active{background:#0f172a;color:#fff;border-color:#0f172a}.product-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px}.product-tile{border:1px solid rgba(15,23,42,.10);background:#fff;border-radius:20px;padding:14px;text-align:left;min-height:132px;display:flex;flex-direction:column;gap:7px;justify-content:space-between;box-shadow:0 8px 20px rgba(15,23,42,.05);transition:.15s ease}.product-tile:hover{transform:translateY(-2px);box-shadow:0 14px 30px rgba(15,23,42,.12)}.product-tile.is-disabled{opacity:.55;cursor:not-allowed}.product-type{font-size:11px;font-weight:900;text-transform:uppercase;letter-spacing:.04em;color:#64748b}.product-price{font-size:18px;font-weight:950;color:#0f172a}.product-stock{font-size:12px;color:#64748b;font-weight:800}.cart-card{padding:16px;position:sticky;top:16px}.cart-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px}.cart-lines{display:flex;flex-direction:column;gap:8px;min-height:160px;max-height:360px;overflow:auto}.empty-cart{color:#94a3b8;text-align:center;padding:45px 10px;background:#f8fafc;border-radius:18px;font-weight:800}.cart-line{display:grid;grid-template-columns:1fr auto;gap:8px;border:1px solid rgba(15,23,42,.08);border-radius:16px;padding:10px;background:#f8fafc}.cart-line-title{font-weight:900}.cart-line-meta{font-size:12px;color:#64748b}.qty-controls{display:flex;align-items:center;gap:4px;justify-content:flex-end}.qty-controls button{width:28px;height:28px;border-radius:10px;border:1px solid #cbd5e1;background:#fff}.qty-controls span{min-width:34px;text-align:center;font-weight:900}.cart-totals{margin-top:14px;border-top:1px solid #e2e8f0;padding-top:12px}.cart-totals div{display:flex;justify-content:space-between;align-items:center;font-size:15px}.cart-totals div:last-child{font-size:22px;margin-top:4px}.receipt-card{border:2px solid rgba(37,99,235,.18)}@media(max-width:1200px){.product-grid{grid-template-columns:repeat(3,minmax(0,1fr))}.pos-layout{grid-template-columns:1fr 340px}}@media(max-width:992px){.pos-layout{grid-template-columns:1fr}.cart-card{position:static}.product-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.pos-topbar{flex-direction:column;align-items:flex-start}}@media(max-width:576px){.product-grid{grid-template-columns:1fr}.product-tile{min-height:110px}}@media print{.pos-products,.pos-cart,.pos-topbar,.alert,.btn{display:none!important}.receipt-card{box-shadow:none!important;border:0!important}}
.subcategory-filter-box{display:block!important;background:#f8fafc;border:1px solid #e2e8f0;border-radius:14px;padding:10px 12px}.subcategory-filter-box select{display:block!important;width:100%;visibility:visible!important;opacity:1!important}</style>

<script>
<?php if ($receipt): ?>
function posPrintReceiptAndReturn(){
    window.print();
    window.setTimeout(function(){
        window.location.href = 'pos.php?store_id=<?php echo (int)$storeId; ?>';
    }, 650);
}
<?php else: ?>
function posPrintReceiptAndReturn(){ window.print(); }
<?php endif; ?>

document.addEventListener('DOMContentLoaded', function(){
    const cart = [];
    const cartJson = document.getElementById('cartJson');
    const cartLines = document.getElementById('cartLines');
    const subtotalText = document.getElementById('subtotalText');
    const totalText = document.getElementById('totalText');
    const paymentMethod = document.getElementById('paymentMethod');
    const roomChargeBox = document.getElementById('roomChargeBox');
    const roomChargeOrder = document.getElementById('roomChargeOrder');
    const postToFolio = document.getElementById('postToFolio');
    const searchInput = document.getElementById('posSearch');
    const subcategorySelect = document.getElementById('posSubcategory');

    function money(n){ return Number(n || 0).toFixed(2); }
    function escapeHtml(str){ return String(str).replace(/[&<>"']/g, s => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#039;'}[s])); }

    function updatePostToFolioOptions(){
        if (!roomChargeOrder || !postToFolio) return;

        const opt = roomChargeOrder.options[roomChargeOrder.selectedIndex];
        let roomFolios = [];

        try {
            roomFolios = JSON.parse(opt ? (opt.getAttribute('data-room-folios') || '[]') : '[]');
        } catch (e) {
            roomFolios = [];
        }

        postToFolio.innerHTML = '';
        const master = document.createElement('option');
        master.value = 'master';
        master.textContent = 'Master Folio (Agent / Main Account)';
        postToFolio.appendChild(master);

        roomFolios.forEach(r => {
            if (!r || !r.rooming_id) return;

            const roomNo = r.room_no || 'N/A';
            const roomType = r.room_type ? ' • ' + r.room_type : '';
            const guest = r.guest ? ' - ' + r.guest : '';

            const roomTarget = Object.assign({}, r, {target_type: 'room'});
            const option = document.createElement('option');
            option.value = JSON.stringify(roomTarget);
            option.textContent = 'Room Folio: Room ' + roomNo + roomType + guest;
            postToFolio.appendChild(option);

            const guestFolios = Array.isArray(r.guest_folios) ? r.guest_folios : [];
            guestFolios.forEach(gf => {
                if (!gf || !gf.folio_id) return;
                const gName = gf.occupant_name || gf.folio_name || 'Guest';
                const gFolio = gf.folio_no ? ' • ' + gf.folio_no : '';
                const guestTarget = Object.assign({}, gf, {target_type: 'guest', room_no: gf.room_no || roomNo});
                const guestOption = document.createElement('option');
                guestOption.value = JSON.stringify(guestTarget);
                guestOption.textContent = 'Guest Folio: ' + gName + ' / Room ' + (gf.room_no || roomNo) + gFolio;
                postToFolio.appendChild(guestOption);
            });
        });
    }

    function syncCart(){
        cartJson.value = JSON.stringify(cart.map(i => ({id:i.id, qty:i.qty})));
        if (!cart.length) {
            cartLines.innerHTML = '<div class="empty-cart">Tap items to add to cart.</div>';
        } else {
            cartLines.innerHTML = cart.map((item, index) => {
                const total = item.qty * item.price;
                return `<div class="cart-line"><div><div class="cart-line-title">${escapeHtml(item.name)}</div><div class="cart-line-meta">${money(item.price)} x ${item.qty}</div></div><div><div class="qty-controls"><button type="button" data-action="minus" data-index="${index}">−</button><span>${item.qty}</span><button type="button" data-action="plus" data-index="${index}">+</button></div><div class="text-end fw-bold mt-1">${money(total)}</div></div></div>`;
            }).join('');
        }
        const subtotal = cart.reduce((sum, item) => sum + (item.qty * item.price), 0);
        subtotalText.textContent = money(subtotal);
        totalText.textContent = money(subtotal);
    }

    document.querySelectorAll('.product-tile').forEach(tile => {
        tile.addEventListener('click', function(){
            if (this.disabled) return;
            const id = parseInt(this.dataset.id || '0', 10);
            const name = this.dataset.name || '';
            const price = parseFloat(this.dataset.price || '0');
            const stock = parseFloat(this.dataset.stock || '0');
            const isStock = this.dataset.stockItem === '1';
            const isRecipe = this.dataset.recipe === '1';
            const existing = cart.find(i => i.id === id);
            if (existing) {
                if (!isRecipe && isStock && existing.qty + 1 > stock) { alert('Not enough stock for ' + name); return; }
                existing.qty += 1;
            } else {
                if (!isRecipe && isStock && stock <= 0) { alert('Out of stock: ' + name); return; }
                cart.push({id, name, price, qty: 1, stock, isStock, isRecipe});
            }
            syncCart();
        });
    });

    cartLines.addEventListener('click', function(e){
        const btn = e.target.closest('button[data-action]');
        if (!btn) return;
        const index = parseInt(btn.dataset.index || '-1', 10);
        if (index < 0 || !cart[index]) return;
        if (btn.dataset.action === 'plus') {
            const item = cart[index];
            if (!item.isRecipe && item.isStock && item.qty + 1 > item.stock) { alert('Not enough stock for ' + item.name); return; }
            item.qty += 1;
        }
        if (btn.dataset.action === 'minus') {
            cart[index].qty -= 1;
            if (cart[index].qty <= 0) cart.splice(index, 1);
        }
        syncCart();
    });

    document.getElementById('clearCart').addEventListener('click', function(){ cart.length = 0; syncCart(); });

    if (paymentMethod) {
        paymentMethod.addEventListener('change', function(){
            roomChargeBox.style.display = this.value === 'room_charge' ? '' : 'none';
            if (this.value === 'room_charge') updatePostToFolioOptions();
        });
    }

    if (roomChargeOrder) {
        roomChargeOrder.addEventListener('change', updatePostToFolioOptions);
    }

    function activeCategory(){
        const active = document.querySelector('.cat-pill.active');
        return active ? (active.dataset.cat || 'all') : 'all';
    }

    function refreshSubcategoryOptions(){
        if (!subcategorySelect) return;
        const cat = activeCategory();
        let currentStillVisible = false;

        Array.from(subcategorySelect.options).forEach(opt => {
            const optCat = opt.getAttribute('data-cat') || 'all';
            const visible = opt.value === 'all' || cat === 'all' || optCat === cat;
            opt.hidden = !visible;
            if (visible && opt.value === subcategorySelect.value) currentStillVisible = true;
        });

        if (!currentStillVisible) subcategorySelect.value = 'all';
    }

    function applyProductFilters(){
        const cat = activeCategory();
        const subcat = subcategorySelect ? (subcategorySelect.value || 'all') : 'all';
        const q = searchInput ? searchInput.value.trim().toLowerCase() : '';

        document.querySelectorAll('.product-tile').forEach(tile => {
            const catOk = cat === 'all' || tile.dataset.cat === cat;
            const subOk = subcat === 'all' || tile.dataset.subcat === subcat;
            const searchOk = !q || (tile.dataset.search || '').includes(q);
            tile.style.display = (catOk && subOk && searchOk) ? '' : 'none';
        });
    }

    document.querySelectorAll('.cat-pill').forEach(btn => {
        btn.addEventListener('click', function(){
            document.querySelectorAll('.cat-pill').forEach(b => b.classList.remove('active'));
            this.classList.add('active');
            refreshSubcategoryOptions();
            applyProductFilters();
        });
    });

    if (subcategorySelect) {
        subcategorySelect.addEventListener('change', applyProductFilters);
        refreshSubcategoryOptions();
    }

    if (searchInput) {
        searchInput.addEventListener('input', applyProductFilters);
    }

    document.getElementById('posForm').addEventListener('submit', function(e){
        if (!cart.length) { e.preventDefault(); alert('Cart is empty.'); return false; }
        if (paymentMethod && paymentMethod.value === 'room_charge') {
            const reservation = document.querySelector('select[name="order_id"]');
            if (!reservation || parseInt(reservation.value || '0', 10) <= 0) { e.preventDefault(); alert('Please select a reservation for room charge.'); return false; }
        }
        syncCart();
    });

    updatePostToFolioOptions();
    syncCart();
});
</script>

<?php require_once __DIR__ . '/../../includes/footer.php'; ?>
