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

$pageTitle = 'Departures Today';

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('fd_column_exists')) {
    function fd_column_exists(PDO $pdo, string $table, string $column): bool
    {
        static $cache = [];
        $key = $table . '.' . $column;

        if (array_key_exists($key, $cache)) {
            return $cache[$key];
        }

        try {
            $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'  => $table,
                ':column_name' => $column,
            ]);
            $cache[$key] = ((int)$stmt->fetchColumn() > 0);
        } catch (Throwable $e) {
            $cache[$key] = false;
        }

        return $cache[$key];
    }
}

if (!function_exists('fd_table_exists')) {
    function fd_table_exists(PDO $pdo, string $table): bool
    {
        static $cache = [];

        if (array_key_exists($table, $cache)) {
            return $cache[$table];
        }

        try {
            $stmt = $pdo->prepare("
                SELECT COUNT(*)
                FROM INFORMATION_SCHEMA.TABLES
                WHERE TABLE_SCHEMA = DATABASE()
                  AND TABLE_NAME = :table_name
            ");
            $stmt->execute([':table_name' => $table]);
            $cache[$table] = ((int)$stmt->fetchColumn() > 0);
        } catch (Throwable $e) {
            $cache[$table] = false;
        }

        return $cache[$table];
    }
}

if (!function_exists('fd_room_dirty_value')) {
    function fd_room_dirty_value(PDO $pdo, string $table, string $column): string
    {
        try {
            $stmt = $pdo->prepare("
                SELECT COLUMN_TYPE
                FROM INFORMATION_SCHEMA.COLUMNS
                WHERE TABLE_SCHEMA = DATABASE()
                  AND TABLE_NAME = :table_name
                  AND COLUMN_NAME = :column_name
                LIMIT 1
            ");
            $stmt->execute([
                ':table_name'  => $table,
                ':column_name' => $column,
            ]);
            $type = strtolower((string)$stmt->fetchColumn());

            if (strpos($type, "enum(") === 0) {
                if (strpos($type, "'dirty'") !== false) {
                    return 'dirty';
                }
                if (strpos($type, "'Dirty'") !== false) {
                    return 'Dirty';
                }
                if (strpos($type, "'vacant_dirty'") !== false) {
                    return 'vacant_dirty';
                }
                if (strpos($type, "'needs_cleaning'") !== false) {
                    return 'needs_cleaning';
                }
                if (strpos($type, "'occupied'") !== false) {
                    return 'dirty';
                }
            }
        } catch (Throwable $e) {
            // Fall through to the safest common value.
        }

        return 'dirty';
    }
}

if (!function_exists('fd_order_checkout_status_value')) {
    function fd_order_checkout_status_value(PDO $pdo): string
    {
        try {
            $stmt = $pdo->prepare("
                SELECT COLUMN_TYPE
                FROM INFORMATION_SCHEMA.COLUMNS
                WHERE TABLE_SCHEMA = DATABASE()
                  AND TABLE_NAME = 'orders'
                  AND COLUMN_NAME = 'status'
                LIMIT 1
            ");
            $stmt->execute();
            $type = strtolower((string)$stmt->fetchColumn());

            if (strpos($type, 'int') !== false || strpos($type, 'tinyint') !== false || strpos($type, 'decimal') !== false) {
                return '4';
            }

            if (strpos($type, "enum(") === 0) {
                foreach (['checked_out', 'checkout', 'completed', 'closed', '4'] as $candidate) {
                    if (strpos($type, "'" . strtolower($candidate) . "'") !== false) {
                        return $candidate;
                    }
                }
            }
        } catch (Throwable $e) {
            // Fall through to legacy numeric checkout status.
        }

        return '4';
    }
}

if (!function_exists('departure_status_badge')) {
    function departure_status_badge(string $status): string
    {
        switch ($status) {
            case 'checked_out':
                return '<span class="badge text-bg-success">Checked Out</span>';
            case 'partial':
                return '<span class="badge text-bg-warning text-dark">Partial Check-Out</span>';
            default:
                return '<span class="badge text-bg-secondary">Pending</span>';
        }
    }
}


if (!function_exists('fd_payment_tx_types')) {
    function fd_payment_tx_types(): array
    {
        return ['payment','receipt','deposit','payment_received','folio_payment','guest_payment'];
    }
}

if (!function_exists('fd_is_payment_tx')) {
    function fd_is_payment_tx(string $txType): bool
    {
        return in_array(strtolower(trim($txType)), fd_payment_tx_types(), true);
    }
}


if (!function_exists('fd_is_void_or_reversal_tx')) {
    function fd_is_void_or_reversal_tx(array $tx): bool
    {
        $txType = strtolower(trim((string)($tx['tx_type'] ?? '')));
        $desc   = strtolower(trim((string)($tx['description'] ?? '')));
        return in_array($txType, ['payment_void','void_payment','payment_reversal','reversal','refund','payment_refund'], true)
            || strpos($desc, 'void') !== false
            || strpos($desc, 'reversal') !== false
            || strpos($desc, 'refund') !== false;
    }
}

if (!function_exists('fd_extra_category_key')) {
    function fd_extra_category_key(array $tx): string
    {
        $category = strtolower(trim((string)($tx['extra_category_name'] ?? $tx['category_name'] ?? '')));
        $txType = strtolower(trim((string)($tx['tx_type'] ?? '')));
        $source = strtolower(trim((string)($tx['source_table'] ?? '')));
        $desc = strtolower(trim((string)($tx['description'] ?? '')));
        $haystack = trim($category . ' ' . $txType . ' ' . $source . ' ' . $desc);

        if (strpos($haystack, 'restaurant') !== false || strpos($haystack, 'food') !== false) return 'restaurant';
        if (strpos($haystack, 'bar') !== false || strpos($haystack, 'drink') !== false || strpos($haystack, 'beverage') !== false) return 'bar';
        if (strpos($haystack, 'spa') !== false || strpos($haystack, 'spar') !== false) return 'spa';
        if (strpos($haystack, 'curio') !== false || strpos($haystack, 'inventory') !== false) return 'curio';
        if (strpos($haystack, 'room_charge') !== false || strpos($haystack, 'room charge') !== false || strpos($haystack, 'accommodation') !== false || strpos($haystack, 'night') !== false) return 'accommodation';
        if ($source === 'restaurant_menu_items') return 'restaurant';
        if ($source === 'inventory_items') return 'curio';
        if ($source === 'tblservices' || strpos($haystack, 'extra') !== false || strpos($haystack, 'laundry') !== false || strpos($haystack, 'transfer') !== false || strpos($haystack, 'park') !== false) return 'extras';
        return 'other';
    }
}

if (!function_exists('fd_category_label')) {
    function fd_category_label(string $key): string
    {
        return [
            'accommodation' => 'Accommodation',
            'restaurant' => 'Restaurant',
            'bar' => 'Bar',
            'spa' => 'Spa',
            'curio' => 'Curio',
            'extras' => 'Other Extras',
            'other' => 'Other Charges',
        ][$key] ?? 'Other Charges';
    }
}

if (!function_exists('fd_recalculate_folio')) {
    function fd_recalculate_folio(PDO $pdo, int $folioId): void
    {
        if ($folioId <= 0 || !fd_table_exists($pdo, 'folios') || !fd_table_exists($pdo, 'folio_transactions')) {
            return;
        }

        $stmt = $pdo->prepare("
            SELECT
                COALESCE(SUM(CASE
                    WHEN COALESCE(is_voided,0)=0
                     AND LOWER(COALESCE(tx_type,'')) NOT IN ('payment','receipt','deposit','payment_received','folio_payment','guest_payment','payment_void','void_payment','payment_reversal','reversal','refund','payment_refund')
                    THEN COALESCE(debit,0) ELSE 0 END),0) AS charges,
                COALESCE(SUM(CASE
                    WHEN COALESCE(is_voided,0)=0
                     AND LOWER(COALESCE(tx_type,'')) IN ('payment','receipt','deposit','payment_received','folio_payment','guest_payment')
                    THEN COALESCE(credit,0) ELSE 0 END),0) AS payments
            FROM folio_transactions
            WHERE folio_id = :folio_id
        ");
        $stmt->execute([':folio_id' => $folioId]);
        $row = $stmt->fetch(PDO::FETCH_ASSOC) ?: [];

        $charges = (float)($row['charges'] ?? 0);
        $payments = (float)($row['payments'] ?? 0);
        $balance = $charges - $payments;

        $set = [];
        $params = [':folio_id' => $folioId];
        if (fd_column_exists($pdo, 'folios', 'total_charges')) {
            $set[] = 'total_charges = :charges';
            $params[':charges'] = $charges;
        }
        if (fd_column_exists($pdo, 'folios', 'total_payments')) {
            $set[] = 'total_payments = :payments';
            $params[':payments'] = $payments;
        }
        if (fd_column_exists($pdo, 'folios', 'balance')) {
            $set[] = 'balance = :balance';
            $params[':balance'] = $balance;
        }
        if (fd_column_exists($pdo, 'folios', 'updated_at')) {
            $set[] = 'updated_at = NOW()';
        }

        if ($set) {
            $pdo->prepare('UPDATE folios SET ' . implode(', ', $set) . ' WHERE id = :folio_id')->execute($params);
        }
    }
}

if (!function_exists('fd_sync_booking_payment_status')) {
    function fd_sync_booking_payment_status(PDO $pdo, int $orderId): void
    {
        if ($orderId <= 0 || !fd_table_exists($pdo, 'folios') || !fd_column_exists($pdo, 'orders', 'payment_status')) {
            return;
        }

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

        $paid = (float)($row['paid'] ?? 0);
        $balance = (float)($row['balance'] ?? 0);
        $status = $paid <= 0 ? 0 : ($balance <= 0.0001 ? 2 : 1);

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

$today = date('Y-m-d');
$selectedDate = trim((string)($_GET['departure_date'] ?? $today));
$search = trim((string)($_GET['q'] ?? ''));
$propertyId = (int)($_GET['property_id'] ?? 0);

$errors = [];
$departures = [];
$messages = [];

if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'move_folio_transaction') {
    try {
        if (function_exists('verify_csrf')) {
            verify_csrf();
        }

        $transactionId = (int)($_POST['transaction_id'] ?? 0);
        $targetFolioId = (int)($_POST['target_folio_id'] ?? 0);
        $moveNote = trim((string)($_POST['move_note'] ?? ''));

        if ($transactionId <= 0) {
            throw new RuntimeException('Please select a charge or payment to move.');
        }
        if ($targetFolioId <= 0) {
            throw new RuntimeException('Please select the destination folio.');
        }
        if (!fd_table_exists($pdo, 'folio_transactions') || !fd_table_exists($pdo, 'folios')) {
            throw new RuntimeException('Folio tables are not available.');
        }

        $pdo->beginTransaction();

        $stmt = $pdo->prepare("
            SELECT
                ft.id,
                ft.folio_id AS source_folio_id,
                ft.order_id,
                ft.description,
                ft.debit,
                ft.credit,
                ft.tx_type,
                fs.order_id AS source_order_id,
                fd.order_id AS target_order_id
            FROM folio_transactions ft
            INNER JOIN folios fs ON fs.id = ft.folio_id
            INNER JOIN folios fd ON fd.id = :target_folio_id
            WHERE ft.id = :transaction_id
            LIMIT 1
            FOR UPDATE
        ");
        $stmt->execute([
            ':target_folio_id' => $targetFolioId,
            ':transaction_id' => $transactionId,
        ]);
        $tx = $stmt->fetch(PDO::FETCH_ASSOC);

        if (!$tx) {
            throw new RuntimeException('Selected transaction was not found.');
        }

        $sourceFolioId = (int)$tx['source_folio_id'];
        $sourceOrderId = (int)($tx['source_order_id'] ?? $tx['order_id'] ?? 0);
        $targetOrderId = (int)($tx['target_order_id'] ?? 0);

        if ($targetFolioId === $sourceFolioId) {
            throw new RuntimeException('The selected transaction is already on that folio.');
        }
        if ($sourceOrderId <= 0 || $targetOrderId <= 0 || $sourceOrderId !== $targetOrderId) {
            throw new RuntimeException('You can only move transactions between folios belonging to the same booking.');
        }

        $setParts = ['folio_id = :target_folio_id'];
        $params = [
            ':target_folio_id' => $targetFolioId,
            ':transaction_id' => $transactionId,
        ];

        if (fd_column_exists($pdo, 'folio_transactions', 'updated_at')) {
            $setParts[] = 'updated_at = NOW()';
        }
        if (fd_column_exists($pdo, 'folio_transactions', 'notes')) {
            $setParts[] = "notes = CONCAT(COALESCE(notes,''), :move_note)";
            $params[':move_note'] = '\nMoved from folio #' . $sourceFolioId . ' to folio #' . $targetFolioId . ' on ' . date('Y-m-d H:i:s') . ($moveNote !== '' ? ' - ' . $moveNote : '');
        }

        $stmt = $pdo->prepare('UPDATE folio_transactions SET ' . implode(', ', $setParts) . ' WHERE id = :transaction_id');
        $stmt->execute($params);

        // Keep linked extra item rows attached to the same folio after a move.
        if (fd_table_exists($pdo, 'extra_charge_items') && fd_column_exists($pdo, 'extra_charge_items', 'folio_id')) {
            $stmtExtraMove = $pdo->prepare("
                UPDATE extra_charge_items
                SET folio_id = :target_folio_id
                WHERE folio_transaction_id = :transaction_id
            ");
            $stmtExtraMove->execute([
                ':target_folio_id' => $targetFolioId,
                ':transaction_id'  => $transactionId,
            ]);
        }

        fd_recalculate_folio($pdo, $sourceFolioId);
        fd_recalculate_folio($pdo, $targetFolioId);
        fd_sync_booking_payment_status($pdo, $sourceOrderId);

        $pdo->commit();

        $_SESSION['flash_success'] = 'Transaction moved successfully between folios.';
        $redirectParams = [
            'departure_date' => $selectedDate,
            'property_id'    => $propertyId,
            'q'              => $search,
        ];
        header('Location: departures_today.php?' . http_build_query($redirectParams));
        exit;
    } catch (Throwable $e) {
        if ($pdo->inTransaction()) {
            $pdo->rollBack();
        }
        $errors[] = 'Move failed: ' . $e->getMessage();
    }
}

if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'checkout_booking') {
    $checkoutOrderId = (int)($_POST['order_id'] ?? 0);

    if ($checkoutOrderId <= 0) {
        $errors[] = 'Invalid booking selected for checkout.';
    } else {
        try {
            $pdo->beginTransaction();

            $stmt = $pdo->prepare("
                SELECT id, order_no, check_out
                FROM orders
                WHERE id = :order_id
                LIMIT 1
                FOR UPDATE
            ");
            $stmt->execute([':order_id' => $checkoutOrderId]);
            $order = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$order) {
                throw new RuntimeException('Booking not found.');
            }

            $stmt = $pdo->prepare("
                SELECT id, room_id
                FROM order_rooming
                WHERE order_id = :order_id
                  AND room_id IS NOT NULL
                  AND room_id > 0
            ");
            $stmt->execute([':order_id' => $checkoutOrderId]);
            $roomingRows = $stmt->fetchAll(PDO::FETCH_ASSOC);

            if (!$roomingRows) {
                throw new RuntimeException('No room allocations found for this booking.');
            }

            $roomIds = [];
            foreach ($roomingRows as $rr) {
                $rid = (int)($rr['room_id'] ?? 0);
                if ($rid > 0) {
                    $roomIds[$rid] = $rid;
                }
            }

            $roomingSetParts = ['checked_out_status = 1'];
            if (fd_column_exists($pdo, 'order_rooming', 'checked_out_at')) {
                $roomingSetParts[] = 'checked_out_at = NOW()';
            }
            if (fd_column_exists($pdo, 'order_rooming', 'checked_out_date')) {
                $roomingSetParts[] = 'checked_out_date = CURDATE()';
            }
            if (fd_column_exists($pdo, 'order_rooming', 'checked_out_time')) {
                $roomingSetParts[] = 'checked_out_time = CURTIME()';
            }

            $stmt = $pdo->prepare("
                UPDATE order_rooming
                SET " . implode(', ', $roomingSetParts) . "
                WHERE order_id = :order_id
            ");
            $stmt->execute([':order_id' => $checkoutOrderId]);

            if (fd_column_exists($pdo, 'orders', 'status')) {
                $statusValue = fd_order_checkout_status_value($pdo);
                $stmt = $pdo->prepare("UPDATE orders SET status = :status WHERE id = :order_id");
                $stmt->execute([
                    ':status'   => $statusValue,
                    ':order_id' => $checkoutOrderId,
                ]);
            }

            $orderSetParts = [];
            if (fd_column_exists($pdo, 'orders', 'checked_out_status')) {
                $orderSetParts[] = 'checked_out_status = 1';
            }
            if (fd_column_exists($pdo, 'orders', 'checked_out_at')) {
                $orderSetParts[] = 'checked_out_at = NOW()';
            }
            if (fd_column_exists($pdo, 'orders', 'actual_check_out')) {
                $orderSetParts[] = 'actual_check_out = NOW()';
            }
            if (fd_column_exists($pdo, 'orders', 'checkout_date')) {
                $orderSetParts[] = 'checkout_date = CURDATE()';
            }

            if ($orderSetParts) {
                $stmt = $pdo->prepare("
                    UPDATE orders
                    SET " . implode(', ', $orderSetParts) . "
                    WHERE id = :order_id
                ");
                $stmt->execute([':order_id' => $checkoutOrderId]);
            }

            if ($roomIds) {
                $roomPlaceholders = implode(',', array_fill(0, count($roomIds), '?'));

                $roomSetParts = [];
                if (fd_column_exists($pdo, 'rooms', 'housekeeping_status')) {
                    $roomSetParts[] = 'housekeeping_status = ' . $pdo->quote(fd_room_dirty_value($pdo, 'rooms', 'housekeeping_status'));
                }
                if (fd_column_exists($pdo, 'rooms', 'status')) {
                    $roomSetParts[] = 'status = ' . $pdo->quote(fd_room_dirty_value($pdo, 'rooms', 'status'));
                }
                if (fd_column_exists($pdo, 'rooms', 'is_dirty')) {
                    $roomSetParts[] = 'is_dirty = 1';
                }
                if (fd_column_exists($pdo, 'rooms', 'dirty_status')) {
                    $roomSetParts[] = 'dirty_status = 1';
                }
                if (fd_column_exists($pdo, 'rooms', 'last_housekeeping_note')) {
                    $roomSetParts[] = 'last_housekeeping_note = ' . $pdo->quote('Marked dirty automatically after checkout');
                }
                if (fd_column_exists($pdo, 'rooms', 'updated_at')) {
                    $roomSetParts[] = 'updated_at = NOW()';
                }

                if ($roomSetParts) {
                    $stmt = $pdo->prepare("
                        UPDATE rooms
                        SET " . implode(', ', array_unique($roomSetParts)) . "
                        WHERE id IN ($roomPlaceholders)
                    ");
                    $stmt->execute(array_values($roomIds));
                }
            }

            $pdo->commit();

            $_SESSION['flash_success'] = 'Booking ' . (($order['order_no'] ?? '') ?: '#' . $checkoutOrderId) . ' checked out. Rooms released and marked dirty.';
            $redirectParams = [
                'departure_date' => $selectedDate,
                'property_id'    => $propertyId,
                'q'              => $search,
            ];
            //header('Location: check_out.php?' . http_build_query($redirectParams));
            exit;
        } catch (Throwable $e) {
            if ($pdo->inTransaction()) {
                $pdo->rollBack();
            }
            $errors[] = 'Checkout failed: ' . $e->getMessage();
        }
    }
}

if (!empty($_SESSION['flash_success'])) {
    $messages[] = (string)$_SESSION['flash_success'];
    unset($_SESSION['flash_success']);
}


$properties = [];
try {
    $stmt = $pdo->query("
        SELECT id, name, code
        FROM properties
        WHERE is_active = 1
        ORDER BY name ASC
    ");
    $properties = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (Throwable $e) {
    $properties = [];
}

$sql = "
    SELECT
        o.*,
        p.name AS property_name,
        p.code AS property_code,
        g.firstname,
        g.lastname,
        CONCAT(COALESCE(a.firstname,''), ' ', COALESCE(a.lastname,'')) AS agent_name,

        (
            SELECT COUNT(*)
            FROM order_rooming rmg
            WHERE rmg.order_id = o.id
        ) AS room_slots_total,

        (
            SELECT COUNT(*)
            FROM order_rooming rmg
            WHERE rmg.order_id = o.id
              AND COALESCE(rmg.checked_out_status,0) = 1
        ) AS room_slots_checked_out,

        (
            SELECT COUNT(*)
            FROM order_rooming rmg
            WHERE rmg.order_id = o.id
              AND COALESCE(rmg.checked_in_status,0) = 1
        ) AS room_slots_checked_in,

        (
            SELECT GROUP_CONCAT(DISTINCT rroom.room_no ORDER BY rroom.room_no SEPARATOR ', ')
            FROM order_rooming rmg
            INNER JOIN rooms rroom ON rroom.id = rmg.room_id
            WHERE rmg.order_id = o.id
        ) AS room_numbers,

        (
            SELECT COALESCE(SUM(f.total_charges),0)
            FROM folios f
            WHERE f.order_id = o.id
        ) AS folio_total_charges,

        (
            SELECT COALESCE(SUM(f.total_payments),0)
            FROM folios f
            WHERE f.order_id = o.id
        ) AS folio_total_payments,

        (
            SELECT COALESCE(SUM(f.balance),0)
            FROM folios f
            WHERE f.order_id = o.id
        ) AS folio_total_balance,

        (
            SELECT GROUP_CONCAT(room_summary SEPARATOR ', ')
            FROM (
                SELECT CONCAT(rt2.title, ' x ', COUNT(*)) AS room_summary
                FROM order_rooming rmg2
                INNER JOIN room_types rt2 ON rt2.id = rmg2.room_type_id
                WHERE rmg2.order_id = o.id
                GROUP BY rmg2.room_type_id, rt2.title
                ORDER BY rt2.title
            ) rmixq
        ) AS room_mix

    FROM orders o
    LEFT JOIN properties p ON p.id = o.property_id
    LEFT JOIN guests g ON g.id = o.guest_id
    LEFT JOIN agents a ON a.id = o.agent_id
    WHERE DATE(o.check_out) = :departure_date
";

$params = [
    ':departure_date' => $selectedDate,
];

if ($propertyId > 0) {
    $sql .= " AND o.property_id = :property_id ";
    $params[':property_id'] = $propertyId;
}

if ($search !== '') {
    $sql .= "
        AND (
            o.order_no LIKE :search
            OR CAST(o.id AS CHAR) LIKE :search
            OR g.firstname LIKE :search
            OR g.lastname LIKE :search
            OR CONCAT(COALESCE(a.firstname,''), ' ', COALESCE(a.lastname,'')) LIKE :search
            OR EXISTS (
                SELECT 1
                FROM order_rooming rmg3
                INNER JOIN room_types rt3 ON rt3.id = rmg3.room_type_id
                WHERE rmg3.order_id = o.id
                  AND rt3.title LIKE :search
            )
        )
    ";
    $params[':search'] = '%' . $search . '%';
}

$sql .= " ORDER BY p.name ASC, o.check_out ASC, o.id DESC ";

try {
    $stmt = $pdo->prepare($sql);
    $stmt->execute($params);
    $departures = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (Throwable $e) {
    $errors[] = $e->getMessage();
}



$chargeBreakdownByOrder = [];
if ($departures && fd_table_exists($pdo, 'folio_transactions')) {
    try {
        $orderIdsForLiveTotals = [];
        foreach ($departures as $depRow) {
            $oid = (int)($depRow['id'] ?? 0);
            if ($oid > 0) {
                $orderIdsForLiveTotals[$oid] = $oid;
                $chargeBreakdownByOrder[$oid] = [
                    'accommodation' => 0.0,
                    'restaurant'    => 0.0,
                    'bar'           => 0.0,
                    'spa'           => 0.0,
                    'curio'         => 0.0,
                    'extras'        => 0.0,
                    'other'         => 0.0,
                    'payments'      => 0.0,
                    'voided'        => 0.0,
                    'balance'       => 0.0,
                ];
            }
        }

        if ($orderIdsForLiveTotals) {
            $orderPlaceholders = implode(',', array_fill(0, count($orderIdsForLiveTotals), '?'));
            $extraJoin = '';
            $extraSelect = "NULL AS extra_item_name, NULL AS extra_item_code, NULL AS extra_category_name";
            if (fd_table_exists($pdo, 'extra_charge_items')) {
                $extraJoin = " LEFT JOIN extra_charge_items eci ON eci.folio_transaction_id = ft.id ";
                $extraSelectParts = [];
                $extraSelectParts[] = fd_column_exists($pdo, 'extra_charge_items', 'item_name') ? 'eci.item_name AS extra_item_name' : 'NULL AS extra_item_name';
                $extraSelectParts[] = fd_column_exists($pdo, 'extra_charge_items', 'item_code') ? 'eci.item_code AS extra_item_code' : 'NULL AS extra_item_code';
                $extraSelectParts[] = fd_column_exists($pdo, 'extra_charge_items', 'category_name') ? 'eci.category_name AS extra_category_name' : 'NULL AS extra_category_name';
                $extraSelect = implode(', ', $extraSelectParts);
            }

            $stmtLive = $pdo->prepare("\n                SELECT\n                    ft.id, ft.order_id, ft.tx_type, ft.description, ft.debit, ft.credit,\n                    COALESCE(ft.is_voided,0) AS is_voided, ft.source_table, ft.source_id,\n                    $extraSelect\n                FROM folio_transactions ft\n                $extraJoin\n                WHERE ft.order_id IN ($orderPlaceholders)\n                ORDER BY ft.order_id ASC, ft.id ASC\n            ");
            $stmtLive->execute(array_values($orderIdsForLiveTotals));
            $liveRows = $stmtLive->fetchAll(PDO::FETCH_ASSOC);

            $liveTotals = [];
            foreach ($orderIdsForLiveTotals as $oid) {
                $liveTotals[$oid] = ['charges' => 0.0, 'payments' => 0.0, 'voided' => 0.0];
            }

            foreach ($liveRows as $tx) {
                $oid = (int)($tx['order_id'] ?? 0);
                if ($oid <= 0 || !isset($liveTotals[$oid])) continue;

                $debit = (float)($tx['debit'] ?? 0);
                $credit = (float)($tx['credit'] ?? 0);
                $isVoided = (int)($tx['is_voided'] ?? 0) === 1;
                $isPayment = fd_is_payment_tx((string)($tx['tx_type'] ?? '')) || in_array(strtolower((string)($tx['source_table'] ?? '')), ['payments','payment','receipts','receipt'], true);
                $isVoidOrReversal = fd_is_void_or_reversal_tx($tx);

                if ($isVoided && $credit > 0) {
                    $liveTotals[$oid]['voided'] += $credit;
                    $chargeBreakdownByOrder[$oid]['voided'] += $credit;
                    continue;
                }
                if ($isVoidOrReversal) {
                    $voidAmount = $debit > 0 ? $debit : abs(min($credit, 0));
                    $liveTotals[$oid]['voided'] += $voidAmount;
                    $chargeBreakdownByOrder[$oid]['voided'] += $voidAmount;
                    continue;
                }
                if ($isPayment && $credit > 0) {
                    $liveTotals[$oid]['payments'] += $credit;
                    $chargeBreakdownByOrder[$oid]['payments'] += $credit;
                    continue;
                }
                if (!$isVoided && $debit > 0) {
                    $liveTotals[$oid]['charges'] += $debit;
                    $key = fd_extra_category_key($tx);
                    if (!isset($chargeBreakdownByOrder[$oid][$key])) $key = 'other';
                    $chargeBreakdownByOrder[$oid][$key] += $debit;
                }
            }

            foreach ($departures as &$depRow) {
                $oid = (int)($depRow['id'] ?? 0);
                if ($oid <= 0 || !isset($liveTotals[$oid])) continue;
                $netPaid = max(0, $liveTotals[$oid]['payments'] - $liveTotals[$oid]['voided']);
                $balance = $liveTotals[$oid]['charges'] - $netPaid;
                $depRow['folio_total_charges'] = round($liveTotals[$oid]['charges'], 2);
                $depRow['folio_total_payments'] = round($netPaid, 2);
                $depRow['folio_total_balance'] = round($balance, 2);
                $chargeBreakdownByOrder[$oid]['balance'] = round($balance, 2);
                $depRow['charge_breakdown_json'] = json_encode($chargeBreakdownByOrder[$oid], JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT);
            }
            unset($depRow);
        }
    } catch (Throwable $e) {
        $errors[] = 'Could not calculate live folio breakdowns: ' . $e->getMessage();
    }
}

$folioSummaryByOrder = [];
if ($departures && fd_table_exists($pdo, 'folios')) {
    try {
        $orderIds = [];
        foreach ($departures as $depRow) {
            $oid = (int)($depRow['id'] ?? 0);
            if ($oid > 0) {
                $orderIds[$oid] = $oid;
                $folioSummaryByOrder[$oid] = [
                    'master' => [],
                    'room'   => [],
                    'guest'  => [],
                    'other'  => [],
                    'all'    => [],
                ];
            }
        }

        if ($orderIds) {
            $placeholders = implode(',', array_fill(0, count($orderIds), '?'));

            $roomJoin = '';
            $roomSelect = "NULL AS folio_room_no";
            if (fd_column_exists($pdo, 'folios', 'room_id') && fd_table_exists($pdo, 'rooms')) {
                $roomJoin = " LEFT JOIN rooms fr ON fr.id = f.room_id ";
                if (fd_column_exists($pdo, 'rooms', 'room_no')) {
                    $roomSelect = "fr.room_no AS folio_room_no";
                } elseif (fd_column_exists($pdo, 'rooms', 'room_number')) {
                    $roomSelect = "fr.room_number AS folio_room_no";
                }
            }

            $guestJoin = '';
            $guestSelect = "NULL AS folio_guest_name";
            if (fd_column_exists($pdo, 'folios', 'guest_id') && fd_table_exists($pdo, 'guests')) {
                $guestJoin = " LEFT JOIN guests fg ON fg.id = f.guest_id ";
                $guestSelect = "TRIM(CONCAT(COALESCE(fg.firstname,''), ' ', COALESCE(fg.lastname,''))) AS folio_guest_name";
            }

            $folioNoSelect = fd_column_exists($pdo, 'folios', 'folio_no') ? 'f.folio_no' : 'NULL AS folio_no';
            $folioNameSelect = fd_column_exists($pdo, 'folios', 'folio_name') ? 'f.folio_name' : 'NULL AS folio_name';
            $folioTypeSelect = fd_column_exists($pdo, 'folios', 'folio_type') ? 'f.folio_type' : "'master' AS folio_type";
            $statusWhere = fd_column_exists($pdo, 'folios', 'status') ? " AND COALESCE(f.status,1) = 1 " : '';

            $stmt = $pdo->prepare("
                SELECT
                    f.id,
                    f.order_id,
                    $folioNoSelect,
                    $folioNameSelect,
                    $folioTypeSelect,
                    COALESCE(f.total_charges,0) AS total_charges,
                    COALESCE(f.total_payments,0) AS total_payments,
                    COALESCE(f.balance,0) AS balance,
                    $roomSelect,
                    $guestSelect
                FROM folios f
                $roomJoin
                $guestJoin
                WHERE f.order_id IN ($placeholders)
                $statusWhere
                ORDER BY FIELD(LOWER(COALESCE(f.folio_type,'master')), 'master', 'room', 'guest'), f.id ASC
            ");
            $stmt->execute(array_values($orderIds));
            $folioRows = $stmt->fetchAll(PDO::FETCH_ASSOC);

            $folioIndex = [];
            foreach ($folioRows as $folio) {
                $oid = (int)($folio['order_id'] ?? 0);
                if ($oid <= 0) {
                    continue;
                }

                $type = strtolower(trim((string)($folio['folio_type'] ?? 'master')));
                if ($type === 'main') {
                    $type = 'master';
                }
                if (!in_array($type, ['master', 'room', 'guest'], true)) {
                    $type = 'other';
                }

                $labelParts = [];
                if (!empty($folio['folio_no'])) {
                    $labelParts[] = (string)$folio['folio_no'];
                }
                if (!empty($folio['folio_name'])) {
                    $labelParts[] = (string)$folio['folio_name'];
                }
                if ($type === 'room' && !empty($folio['folio_room_no'])) {
                    $labelParts[] = 'Room ' . (string)$folio['folio_room_no'];
                }
                if ($type === 'guest' && !empty($folio['folio_guest_name'])) {
                    $labelParts[] = (string)$folio['folio_guest_name'];
                }
                if (!$labelParts) {
                    $labelParts[] = ucfirst($type) . ' Folio #' . (int)$folio['id'];
                }

                $folio['folio_type_normalized'] = $type;
                $folio['display_label'] = implode(' • ', array_unique(array_filter($labelParts)));
                $folio['transactions'] = [
                    'charges' => [],
                    'payments' => [],
                    'other' => [],
                ];

                $folioId = (int)$folio['id'];
                $folioIndex[$folioId] = ['order_id' => $oid, 'type' => $type, 'offset' => count($folioSummaryByOrder[$oid][$type])];
                $folioSummaryByOrder[$oid][$type][] = $folio;
                $folioSummaryByOrder[$oid]['all'][] = [
                    'id' => $folioId,
                    'type' => $type,
                    'label' => $folio['display_label'],
                    'balance' => (float)$folio['balance'],
                ];
            }

            if ($folioIndex && fd_table_exists($pdo, 'folio_transactions')) {
                $folioIds = array_keys($folioIndex);
                $folioPlaceholders = implode(',', array_fill(0, count($folioIds), '?'));

                $txDate = fd_column_exists($pdo, 'folio_transactions', 'tx_date') ? 'ft.tx_date' : (fd_column_exists($pdo, 'folio_transactions', 'created_at') ? 'ft.created_at' : 'NULL AS tx_date');
                $txType = fd_column_exists($pdo, 'folio_transactions', 'tx_type') ? 'ft.tx_type' : "'' AS tx_type";
                $description = fd_column_exists($pdo, 'folio_transactions', 'description') ? 'ft.description' : "'' AS description";
                $debit = fd_column_exists($pdo, 'folio_transactions', 'debit') ? 'ft.debit' : '0 AS debit';
                $credit = fd_column_exists($pdo, 'folio_transactions', 'credit') ? 'ft.credit' : '0 AS credit';
                $isVoided = fd_column_exists($pdo, 'folio_transactions', 'is_voided') ? 'ft.is_voided' : '0 AS is_voided';

                $sourceTable = fd_column_exists($pdo, 'folio_transactions', 'source_table') ? 'ft.source_table' : 'NULL AS source_table';
                $sourceId = fd_column_exists($pdo, 'folio_transactions', 'source_id') ? 'ft.source_id' : 'NULL AS source_id';


                $extraJoin = '';
                $extraSelect = "NULL AS extra_item_name, NULL AS extra_item_code, NULL AS extra_category_name, NULL AS extra_quantity, NULL AS extra_unit_price, NULL AS extra_line_total";
                if (fd_table_exists($pdo, 'extra_charge_items')) {
                    $extraJoin = " LEFT JOIN extra_charge_items eci ON eci.folio_transaction_id = ft.id ";
                    $extraSelectParts = [];
                    $extraSelectParts[] = fd_column_exists($pdo, 'extra_charge_items', 'item_name') ? 'eci.item_name AS extra_item_name' : 'NULL AS extra_item_name';
                    $extraSelectParts[] = fd_column_exists($pdo, 'extra_charge_items', 'item_code') ? 'eci.item_code AS extra_item_code' : 'NULL AS extra_item_code';
                    $extraSelectParts[] = fd_column_exists($pdo, 'extra_charge_items', 'category_name') ? 'eci.category_name AS extra_category_name' : 'NULL AS extra_category_name';
                    $extraSelectParts[] = fd_column_exists($pdo, 'extra_charge_items', 'qty') ? 'eci.qty AS extra_quantity' : (fd_column_exists($pdo, 'extra_charge_items', 'quantity') ? 'eci.quantity AS extra_quantity' : 'NULL AS extra_quantity');
                    $extraSelectParts[] = fd_column_exists($pdo, 'extra_charge_items', 'unit_price') ? 'eci.unit_price AS extra_unit_price' : 'NULL AS extra_unit_price';
                    $extraSelectParts[] = fd_column_exists($pdo, 'extra_charge_items', 'line_total') ? 'eci.line_total AS extra_line_total' : 'NULL AS extra_line_total';
                    $extraSelect = implode(', ', $extraSelectParts);
                }

                $stmt = $pdo->prepare("
                    SELECT
                        ft.id,
                        ft.folio_id,
                        ft.order_id,
                        $txDate,
                        $txType,
                        $description,
                        $debit,
                        $credit,
                        $isVoided,
                        $sourceTable,
                        $sourceId,
                        $extraSelect
                    FROM folio_transactions ft
                    $extraJoin
                    WHERE ft.folio_id IN ($folioPlaceholders)
                    ORDER BY ft.folio_id ASC, COALESCE(ft.tx_date, ft.created_at) ASC, ft.id ASC
                    LIMIT 2500
                ");
                $stmt->execute($folioIds);
                $txRows = $stmt->fetchAll(PDO::FETCH_ASSOC);

                foreach ($txRows as $tx) {
                    $folioId = (int)($tx['folio_id'] ?? 0);
                    if (!isset($folioIndex[$folioId])) {
                        continue;
                    }

                    $debitValue = (float)($tx['debit'] ?? 0);
                    $creditValue = (float)($tx['credit'] ?? 0);
                    $txTypeValue = strtolower(trim((string)($tx['tx_type'] ?? '')));
                    $group = 'other';
                    if ($creditValue > 0 || fd_is_payment_tx($txTypeValue)) {
                        $group = 'payments';
                    } elseif ($debitValue > 0) {
                        $group = 'charges';
                    }

                    $categoryKey = fd_extra_category_key($tx);
                    $tx['charge_category'] = fd_category_label($categoryKey);
                    $itemName = trim((string)($tx['extra_item_name'] ?? ''));
                    if ($itemName !== '') {
                        $qty = (float)($tx['extra_quantity'] ?? 0);
                        $unit = (float)($tx['extra_unit_price'] ?? 0);
                        $code = trim((string)($tx['extra_item_code'] ?? ''));
                        $display = $tx['charge_category'] . ' - ' . $itemName;
                        if ($code !== '') $display .= ' [' . $code . ']';
                        if ($qty != 0 || $unit != 0) $display .= ' x ' . money_fmt($qty) . ' @ ' . money_fmt($unit);
                        $tx['display_description'] = $display;
                    } else {
                        $tx['display_description'] = (string)($tx['description'] ?? $txTypeValue ?: 'Transaction');
                    }

                    $idx = $folioIndex[$folioId];
                    $folioSummaryByOrder[$idx['order_id']][$idx['type']][$idx['offset']]['transactions'][$group][] = $tx;
                }
            }
        }
    } catch (Throwable $e) {
        $errors[] = 'Could not load folio summary details: ' . $e->getMessage();
    }
}

$totalDepartures = count($departures);
$totalPending = 0;
$totalCheckedOut = 0;
$totalPartial = 0;

foreach ($departures as $row) {
    $slotsTotal = (int)($row['room_slots_total'] ?? 0);
    $slotsChecked = (int)($row['room_slots_checked_out'] ?? 0);

    if ($slotsTotal > 0 && $slotsChecked >= $slotsTotal) {
        $totalCheckedOut++;
    } elseif ($slotsChecked > 0) {
        $totalPartial++;
    } else {
        $totalPending++;
    }
}

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

<div class="frontdesk-topbar compact-departures-top mb-2">
    <div class="d-flex flex-wrap align-items-center justify-content-between gap-2">
        <div>
            <div class="page-eyebrow mb-1"><i class="bi bi-calendar-x"></i> Front Desk</div>
            <h4 class="mb-0 fw-bold">Departures</h4>
            <div class="small text-muted">Checkout control, room release, dirty-room handover.</div>
        </div>
        <a href="/rooms/modules/reservations/reservation_list.php" class="btn btn-sm btn-outline-secondary">
            <i class="bi bi-arrow-left me-1"></i>Reservations
        </a>
    </div>
</div>

<?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 ($messages): ?>
    <div class="alert alert-success py-2 mb-2">
        <?php foreach ($messages as $msg): ?>
            <div><?php echo h($msg); ?></div>
        <?php endforeach; ?>
    </div>
<?php endif; ?>

<div class="row g-2 mb-2 departure-metrics compact-metrics">
    <div class="col-sm-6 col-xl-3">
        <div class="metric-card">
            <div class="metric-icon bg-primary-subtle text-primary">
                <i class="bi bi-box-arrow-right"></i>
            </div>
            <div>
                <div class="metric-label">Departures</div>
                <div class="metric-value"><?php echo number_format($totalDepartures); ?></div>
            </div>
        </div>
    </div>

    <div class="col-sm-6 col-xl-3">
        <div class="metric-card">
            <div class="metric-icon bg-secondary-subtle text-secondary">
                <i class="bi bi-hourglass-split"></i>
            </div>
            <div>
                <div class="metric-label">Pending</div>
                <div class="metric-value"><?php echo number_format($totalPending); ?></div>
            </div>
        </div>
    </div>

    <div class="col-sm-6 col-xl-3">
        <div class="metric-card">
            <div class="metric-icon bg-warning-subtle text-warning">
                <i class="bi bi-person-dash"></i>
            </div>
            <div>
                <div class="metric-label">Partial</div>
                <div class="metric-value"><?php echo number_format($totalPartial); ?></div>
            </div>
        </div>
    </div>

    <div class="col-sm-6 col-xl-3">
        <div class="metric-card">
            <div class="metric-icon bg-success-subtle text-success">
                <i class="bi bi-check2-circle"></i>
            </div>
            <div>
                <div class="metric-label">Checked Out</div>
                <div class="metric-value"><?php echo number_format($totalCheckedOut); ?></div>
            </div>
        </div>
    </div>
</div>

<div class="card panel-card mb-2 compact-filter-card">
    <div class="card-body p-2">
        <form method="get" class="row g-2 align-items-end">
            <div class="col-md-3">
                <label class="form-label">Departure Date</label>
                <input type="date" name="departure_date" class="form-control" value="<?php echo h($selectedDate); ?>">
            </div>

            <div class="col-md-3">
                <label class="form-label">Property</label>
                <select name="property_id" class="form-select">
                    <option value="0">All properties</option>
                    <?php foreach ($properties as $property): ?>
                        <option value="<?php echo (int)$property['id']; ?>" <?php echo $propertyId === (int)$property['id'] ? 'selected' : ''; ?>>
                            <?php echo h($property['name']); ?><?php echo !empty($property['code']) ? ' - ' . h($property['code']) : ''; ?>
                        </option>
                    <?php endforeach; ?>
                </select>
            </div>

            <div class="col-md-5">
                <label class="form-label">Search</label>
                <input type="text" name="q" class="form-control" value="<?php echo h($search); ?>" placeholder="Booking no, guest, agent, room type...">
            </div>

            <div class="col-md-1 d-grid">
                <button class="btn btn-primary">Go</button>
            </div>
        </form>
    </div>
</div>

<div class="card panel-card">
    <div class="card-header d-flex justify-content-between align-items-center">
        <div>
            <h5 class="mb-0">Departure List</h5>
            <small>Bookings departing on <?php echo h($selectedDate); ?> • Double-click a booking row to view folio balances</small>
        </div>
    </div>

    <div class="card-body p-0">
        <div class="table-responsive departure-table-wrap">
            <table class="table table-modern align-middle mb-0 departure-table">
                <thead>
                    <tr>
                        <th>Booking</th>
                        <th>Property</th>
                        <th>Guest</th>
                        <th>Agent</th>
                        <th>Stay</th>
                        <th>Room Mix / Pax</th>
                        <th>Check-Out Status</th>
                        <th class="text-end">Folio Balance</th>
                        <th class="text-end">Actions</th>
                    </tr>
                </thead>
                <tbody>
                    <?php if (!$departures): ?>
                        <tr>
                            <td colspan="9" class="text-center text-muted py-5">
                                No departures found for the selected date.
                            </td>
                        </tr>
                    <?php else: ?>
                        <?php foreach ($departures as $row): ?>
                            <?php
                            $guestName = trim(($row['firstname'] ?? '') . ' ' . ($row['lastname'] ?? ''));
                            if ($guestName === '') {
                                $guestName = 'Guest';
                            }

                            $agentName = trim((string)($row['agent_name'] ?? ''));
                            if ($agentName === '') {
                                $agentName = 'Direct';
                            }

                            $propertyLabel = trim((string)($row['property_name'] ?? ''));
                            if (!empty($row['property_code'])) {
                                $propertyLabel .= ($propertyLabel !== '' ? ' (' . $row['property_code'] . ')' : $row['property_code']);
                            }

                            $slotsTotal = (int)($row['room_slots_total'] ?? 0);
                            $slotsChecked = (int)($row['room_slots_checked_out'] ?? 0);

                            if ($slotsTotal > 0 && $slotsChecked >= $slotsTotal) {
                                $departureStatus = 'checked_out';
                            } elseif ($slotsChecked > 0) {
                                $departureStatus = 'partial';
                            } else {
                                $departureStatus = 'pending';
                            }

                            $balance = (float)($row['folio_total_balance'] ?? 0);
                            $roomMix = trim((string)($row['room_mix'] ?? ''));
                            $orderIdForModal = (int)$row['id'];
                            $modalFolios = $folioSummaryByOrder[$orderIdForModal] ?? ['master' => [], 'room' => [], 'guest' => [], 'other' => []];
                            $modalFolioJson = h(json_encode($modalFolios, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT));
                            ?>
                            <tr class="booking-folio-row"
                                data-order-id="<?php echo $orderIdForModal; ?>"
                                data-booking="<?php echo h($row['order_no'] ?: ('#' . $row['id'])); ?>"
                                data-guest="<?php echo h($guestName); ?>"
                                data-property="<?php echo h($propertyLabel !== '' ? $propertyLabel : 'Not set'); ?>"
                                data-rooms="<?php echo h($row['room_numbers'] ?: 'Not allocated'); ?>"
                                data-balance="<?php echo h(money_fmt($balance)); ?>"
                                data-breakdown="<?php echo h($row['charge_breakdown_json'] ?? '{}'); ?>"
                                data-folios="<?php echo $modalFolioJson; ?>">
                                <td>
                                    <div class="data-stack">
                                        <strong><?php echo h($row['order_no'] ?: ('#' . $row['id'])); ?></strong>
                                        <small>Booking ID <?php echo (int)$row['id']; ?></small>
                                    </div>
                                </td>

                                <td><?php echo h($propertyLabel !== '' ? $propertyLabel : 'Not set'); ?></td>
                                <td><?php echo h($guestName); ?></td>
                                <td><?php echo h($agentName); ?></td>

                                <td>
                                    <div class="data-stack">
                                        <strong><?php echo h($row['check_in']); ?></strong>
                                        <small>to <?php echo h($row['check_out']); ?></small>
                                    </div>
                                </td>

                                <td>
                                    <?php if ($roomMix !== ''): ?>
                                        <div class="fw-semibold"><?php echo h($roomMix); ?></div>
                                    <?php else: ?>
                                        <div class="text-muted">Room mix not set</div>
                                    <?php endif; ?>
                                    <div class="small text-muted mt-1">
                                        <?php echo (int)($row['totalrooms'] ?? 1); ?> room(s) •
                                        <?php echo (int)($row['adults'] ?? 0); ?>A /
                                        <?php echo (int)($row['kids'] ?? 0); ?>C
                                    </div>
                                    <?php if (!empty($row['room_numbers'])): ?>
                                        <div class="small text-muted mt-1">Rooms: <?php echo h($row['room_numbers']); ?></div>
                                    <?php endif; ?>
                                    <div class="small text-muted mt-1">
                                        Room slots checked out: <?php echo $slotsChecked; ?>/<?php echo $slotsTotal; ?>
                                    </div>
                                </td>

                                <td><?php echo departure_status_badge($departureStatus); ?></td>

                                <td class="text-end">
                                    <span class="badge text-bg-<?php echo abs($balance) > 0.00001 ? 'warning' : 'success'; ?> px-3 py-2">
                                        <?php echo money_fmt($balance); ?>
                                    </span>
                                    <?php $bd = $chargeBreakdownByOrder[$orderIdForModal] ?? []; ?>
                                    <?php if ($bd): ?>
                                        <div class="small text-muted mt-1">
                                            R <?php echo money_fmt($bd['restaurant'] ?? 0); ?> •
                                            B <?php echo money_fmt($bd['bar'] ?? 0); ?> •
                                            Spa <?php echo money_fmt($bd['spa'] ?? 0); ?> •
                                            Curio <?php echo money_fmt($bd['curio'] ?? 0); ?>
                                        </div>
                                    <?php endif; ?>
                                </td>

                                <td class="text-end">
                                    <div class="d-inline-flex gap-2 flex-wrap justify-content-end">
                                        <?php if ($departureStatus !== 'checked_out'): ?>
                                            <form method="post" class="d-inline" onsubmit="return confirm('Complete checkout, release rooms, and mark rooms dirty?');">
                                                <input type="hidden" name="action" value="checkout_booking">
                                                <input type="hidden" name="order_id" value="<?php echo (int)$row['id']; ?>">
                                                <button type="submit" class="btn btn-sm btn-danger">
                                                    <i class="bi bi-door-closed me-1"></i>Check Out
                                                </button>
                                            </form>
                                        <?php else: ?>
                                            <span class="badge text-bg-success px-3 py-2">
                                                <i class="bi bi-check2-circle me-1"></i>Completed
                                            </span>
                                        <?php endif; ?>

                                        <a href="/rooms/modules/payments/payments.php?order_id=<?php echo (int)$row['id']; ?>"
                                           class="btn btn-sm btn-outline-primary">
                                            <i class="bi bi-cash-stack me-1"></i>Payments
                                        </a>

                                        <a href="/rooms/modules/payments/folio.php?q=<?php echo urlencode((string)($row['order_no'] ?: $row['id'])); ?>"
                                           class="btn btn-sm btn-outline-secondary">
                                            <i class="bi bi-receipt me-1"></i>Folios
                                        </a>

                                        <button type="button"
                                                class="btn btn-sm btn-outline-success view-folio-summary"
                                                data-order-id="<?php echo (int)$row['id']; ?>">
                                            <i class="bi bi-window-stack me-1"></i>Balances
                                        </button>

                                        <div class="dropdown proforma-action-menu">
                                            <button class="btn btn-sm btn-outline-dark dropdown-toggle"
                                                    type="button"
                                                    data-bs-toggle="dropdown"
                                                    data-bs-boundary="viewport"
                                                    data-bs-display="dynamic"
                                                    aria-expanded="false">
                                                <i class="bi bi-file-earmark-pdf me-1"></i>Proformas
                                            </button>
                                            <ul class="dropdown-menu dropdown-menu-end proforma-dropdown-menu">
                                                <li>
                                                    <a class="dropdown-item proforma-item proforma-standard"
                                                       href="/rooms/modules/payments/proforma_invoice.php?order_id=<?php echo (int)$row['id']; ?>"
                                                       target="_blank" rel="noopener">
                                                        <span class="proforma-icon"><i class="bi bi-file-earmark-pdf"></i></span>
                                                        <span>
                                                            <strong>Proforma</strong>
                                                            <small>Full booking proforma</small>
                                                        </span>
                                                    </a>
                                                </li>
                                                <li>
                                                    <a class="dropdown-item proforma-item proforma-master"
                                                       href="/rooms/modules/payments/proforma_master_folio.php?order_id=<?php echo (int)$row['id']; ?>"
                                                       target="_blank" rel="noopener">
                                                        <span class="proforma-icon"><i class="bi bi-collection"></i></span>
                                                        <span>
                                                            <strong>Main Folio Proforma</strong>
                                                            <small>Master / agent account</small>
                                                        </span>
                                                    </a>
                                                </li>
                                                <li>
                                                    <a class="dropdown-item proforma-item proforma-room"
                                                       href="/rooms/modules/payments/proforma_room_account.php?order_id=<?php echo (int)$row['id']; ?>"
                                                       target="_blank" rel="noopener">
                                                        <span class="proforma-icon"><i class="bi bi-door-open"></i></span>
                                                        <span>
                                                            <strong>Room Proforma</strong>
                                                            <small>Guest / room account</small>
                                                        </span>
                                                    </a>
                                                </li>
                                            </ul>
                                        </div>

                                        <a href="/rooms/modules/reservations/reservation_view.php?order_id=<?php echo (int)$row['id']; ?>"
                                           class="btn btn-sm btn-light">
                                            <i class="bi bi-eye me-1"></i>View
                                        </a>
                                    </div>
                                </td>
                            </tr>
                        <?php endforeach; ?>
                    <?php endif; ?>
                </tbody>
            </table>
        </div>
    </div>
</div>



<div class="modal fade" id="folioBalanceModal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog modal-xl modal-dialog-scrollable">
        <div class="modal-content folio-balance-modal">
            <div class="modal-header">
                <div>
                    <h5 class="modal-title mb-1"><i class="bi bi-wallet2 me-2"></i>Folio Control Centre</h5>
                    <div class="small text-muted" id="folioModalSubtitle">Double-click a booking row to view balances, print proformas, or move charges/payments.</div>
                </div>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <div class="modal-body">
                <div class="row g-3 mb-3">
                    <div class="col-md-3"><div class="folio-mini-card"><span>Booking</span><strong id="folioModalBooking">-</strong></div></div>
                    <div class="col-md-3"><div class="folio-mini-card"><span>Guest</span><strong id="folioModalGuest">-</strong></div></div>
                    <div class="col-md-3"><div class="folio-mini-card"><span>Rooms</span><strong id="folioModalRooms">-</strong></div></div>
                    <div class="col-md-3"><div class="folio-mini-card"><span>Total Balance</span><strong id="folioModalBalance">0.00</strong></div></div>
                </div>

                <div class="folio-breakdown-grid mb-3" id="folioBreakdownGrid"></div>

                <div class="folio-action-strip mb-3">
                    <a href="#" target="_blank" rel="noopener" class="btn btn-sm btn-danger" id="folioPrintFull">
                        <i class="bi bi-file-earmark-pdf me-1"></i>Full Proforma
                    </a>
                    <a href="#" target="_blank" rel="noopener" class="btn btn-sm btn-primary" id="folioPrintMaster">
                        <i class="bi bi-collection me-1"></i>Main Folio Proforma
                    </a>
                    <a href="#" target="_blank" rel="noopener" class="btn btn-sm btn-success" id="folioPrintRoom">
                        <i class="bi bi-door-open me-1"></i>Room Proforma
                    </a>
                    <a href="#" target="_blank" rel="noopener" class="btn btn-sm btn-warning" id="folioPrintGuest">
                        <i class="bi bi-person-badge me-1"></i>Guest Folio Selector
                    </a>
                </div>

                <div class="move-panel mb-3" id="movePanel" style="display:none;">
                    <form method="post" class="row g-2 align-items-end" id="moveTransactionForm" onsubmit="return confirm('Move this transaction to the selected folio and recalculate balances?');">
                        <?php if (function_exists('csrf_field')) echo csrf_field(); ?>
                        <input type="hidden" name="action" value="move_folio_transaction">
                        <input type="hidden" name="transaction_id" id="moveTransactionId">
                        <div class="col-lg-4">
                            <label class="form-label">Selected Transaction</label>
                            <input type="text" class="form-control" id="moveTransactionLabel" readonly>
                        </div>
                        <div class="col-lg-4">
                            <label class="form-label">Move To Folio</label>
                            <select name="target_folio_id" id="moveTargetFolio" class="form-select" required></select>
                        </div>
                        <div class="col-lg-3">
                            <label class="form-label">Reason / Note</label>
                            <input type="text" name="move_note" class="form-control" placeholder="Optional">
                        </div>
                        <div class="col-lg-1 d-grid">
                            <button class="btn btn-dark">Move</button>
                        </div>
                    </form>
                </div>

                <div class="alert alert-info py-2 small">
                    <strong>Tip:</strong> Expand any folio to view charges and payments. Use <strong>Move</strong> beside a line to transfer it to another folio in the same booking.
                </div>

                <div class="row g-3">
                    <div class="col-lg-4">
                        <div class="folio-section-card">
                            <div class="folio-section-title master"><i class="bi bi-collection me-2"></i>Main / Master Folio</div>
                            <div id="folioMasterList" class="folio-list"></div>
                        </div>
                    </div>
                    <div class="col-lg-4">
                        <div class="folio-section-card">
                            <div class="folio-section-title room"><i class="bi bi-door-open me-2"></i>Room Folios</div>
                            <div id="folioRoomList" class="folio-list"></div>
                        </div>
                    </div>
                    <div class="col-lg-4">
                        <div class="folio-section-card">
                            <div class="folio-section-title guest"><i class="bi bi-person-badge me-2"></i>Guest Folios</div>
                            <div id="folioGuestList" class="folio-list"></div>
                        </div>
                    </div>
                </div>

                <div id="folioOtherWrap" class="folio-section-card mt-3" style="display:none;">
                    <div class="folio-section-title other"><i class="bi bi-folder2-open me-2"></i>Other Folios</div>
                    <div id="folioOtherList" class="folio-list"></div>
                </div>
            </div>
            <div class="modal-footer">
                <a href="#" target="_blank" rel="noopener" class="btn btn-outline-primary" id="folioModalPaymentsLink">
                    <i class="bi bi-cash-stack me-1"></i>Open Payments
                </a>
                <a href="#" target="_blank" rel="noopener" class="btn btn-outline-secondary" id="folioModalFoliosLink">
                    <i class="bi bi-receipt me-1"></i>Open Folios
                </a>
                <button type="button" class="btn btn-dark" data-bs-dismiss="modal">Close</button>
            </div>
        </div>
    </div>
</div>

<style>
.compact-departures-top{background:#fff;border:1px solid #edf2f7;border-radius:16px;padding:10px 14px;box-shadow:0 8px 22px rgba(15,23,42,.045)}
.compact-departures-top .page-eyebrow{color:#64748b;font-size:.72rem;text-transform:uppercase;letter-spacing:.08em;font-weight:800}
.compact-metrics .metric-card{min-height:auto;padding:10px 12px;border-radius:14px}.compact-metrics .metric-icon{width:34px;height:34px;border-radius:10px;font-size:.95rem}.compact-metrics .metric-label{font-size:.74rem;margin-bottom:0}.compact-metrics .metric-value{font-size:1.05rem;line-height:1.1}
.compact-filter-card .form-label{font-size:.76rem;font-weight:700;margin-bottom:.15rem}.compact-filter-card .form-control,.compact-filter-card .form-select{min-height:34px;padding:.35rem .65rem;font-size:.86rem}.compact-filter-card .btn{min-height:34px;padding:.35rem .65rem}
.departure-table-wrap{max-height:calc(100vh - 280px);overflow:auto}.departure-table thead th{position:sticky;top:0;z-index:8;background:#fff;box-shadow:0 1px 0 #e5e7eb}.departure-table td,.departure-table th{font-size:.86rem;padding:.55rem .65rem}.departure-table .btn{padding:.28rem .5rem;font-size:.78rem}
.proforma-action-menu{position:relative}.proforma-action-menu .dropdown-toggle{border-radius:999px;font-weight:800}.proforma-dropdown-menu{min-width:260px;border:1px solid #e5e7eb;border-radius:16px;padding:7px;box-shadow:0 18px 45px rgba(15,23,42,.18)}.proforma-item{display:flex!important;align-items:center;gap:10px;border-radius:13px!important;padding:9px 10px!important;transition:background .14s ease,transform .14s ease}.proforma-item:hover,.proforma-item:focus{transform:translateX(2px)}.proforma-item .proforma-icon{width:34px;height:34px;border-radius:12px;display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto}.proforma-item strong{display:block;font-size:.80rem;line-height:1.1}.proforma-item small{display:block;font-size:.67rem;color:#64748b;margin-top:2px}.proforma-standard .proforma-icon{background:#fee2e2;color:#dc2626}.proforma-master .proforma-icon{background:#e0e7ff;color:#4338ca}.proforma-room .proforma-icon{background:#dcfce7;color:#15803d}.proforma-standard:hover{background:#fff1f2!important}.proforma-master:hover{background:#eef2ff!important}.proforma-room:hover{background:#f0fdf4!important}.proforma-action-menu .dropdown-menu[data-bs-popper]{margin-top:.35rem}
.booking-folio-row{cursor:pointer}.booking-folio-row:hover{background:#f8fafc}.folio-balance-modal .modal-header{background:#f8fafc;border-bottom:1px solid #e5e7eb}.folio-mini-card{border:1px solid #e5e7eb;border-radius:16px;padding:12px 14px;background:#fff;min-height:76px;box-shadow:0 8px 22px rgba(15,23,42,.045)}.folio-mini-card span{display:block;font-size:.72rem;text-transform:uppercase;letter-spacing:.06em;color:#64748b;font-weight:800;margin-bottom:4px}.folio-mini-card strong{display:block;font-size:.98rem;color:#0f172a;word-break:break-word}
.folio-action-strip{display:flex;flex-wrap:wrap;gap:8px;border:1px solid #e5e7eb;background:#f8fafc;border-radius:16px;padding:10px}.move-panel{border:1px solid #cbd5e1;background:#fff;border-radius:16px;padding:12px;box-shadow:0 8px 24px rgba(15,23,42,.06)}
.folio-breakdown-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px}.folio-breakdown-pill{border:1px solid #e5e7eb;border-radius:14px;background:#fff;padding:8px 10px}.folio-breakdown-pill span{display:block;font-size:.68rem;text-transform:uppercase;letter-spacing:.05em;color:#64748b;font-weight:900}.folio-breakdown-pill strong{display:block;margin-top:2px;font-size:.90rem;color:#0f172a}@media(max-width:991.98px){.folio-breakdown-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
.folio-section-card{border:1px solid #e5e7eb;border-radius:18px;background:#fff;overflow:hidden;min-height:220px;box-shadow:0 10px 26px rgba(15,23,42,.05)}.folio-section-title{padding:11px 13px;font-size:.82rem;font-weight:900;text-transform:uppercase;letter-spacing:.05em;border-bottom:1px solid #e5e7eb}.folio-section-title.master{background:#eef2ff;color:#3730a3}.folio-section-title.room{background:#ecfdf5;color:#047857}.folio-section-title.guest{background:#fff7ed;color:#c2410c}.folio-section-title.other{background:#f1f5f9;color:#334155}.folio-list{padding:10px;display:flex;flex-direction:column;gap:8px}
.folio-row{border:1px solid #eef2f7;border-radius:14px;background:#fff;overflow:hidden}.folio-row summary{list-style:none;cursor:pointer;padding:10px}.folio-row summary::-webkit-details-marker{display:none}.folio-row .folio-label{font-weight:800;color:#0f172a;font-size:.86rem;margin-bottom:6px;display:flex;justify-content:space-between;gap:8px}.folio-row .folio-values{display:grid;grid-template-columns:repeat(3,1fr);gap:6px}.folio-row .folio-values span{display:block;background:#f8fafc;border-radius:10px;padding:6px 7px;font-size:.72rem;color:#64748b}.folio-row .folio-values strong{display:block;color:#0f172a;font-size:.82rem;margin-top:2px}.folio-empty{padding:22px 12px;text-align:center;color:#64748b;font-size:.84rem}.folio-balance-positive{color:#b45309!important}.folio-balance-zero{color:#15803d!important}
.folio-tools{display:flex;flex-wrap:wrap;gap:5px;margin-top:8px}.folio-tools .btn{font-size:.70rem;padding:.18rem .42rem}.tx-tree{border-top:1px solid #eef2f7;background:#fbfdff;padding:10px}.tx-group-title{font-size:.72rem;font-weight:900;text-transform:uppercase;color:#475569;margin:6px 0}.tx-row{display:grid;grid-template-columns:84px 1fr 78px 62px;gap:7px;align-items:center;padding:7px;border:1px solid #e5e7eb;background:#fff;border-radius:10px;margin-bottom:6px;font-size:.76rem}.tx-row .tx-desc{min-width:0}.tx-row .tx-desc strong{display:block;color:#0f172a}.tx-row .tx-desc small{display:block;color:#64748b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tx-row .tx-amount{text-align:right;font-weight:900}.tx-row.is-payment .tx-amount{color:#15803d}.tx-row.is-charge .tx-amount{color:#b45309}.tx-row.is-void{opacity:.55;text-decoration:line-through}.tx-empty{font-size:.76rem;color:#64748b;padding:7px}.select-move-btn{font-size:.70rem;padding:.18rem .4rem}
@media(max-width:767.98px){.tx-row{grid-template-columns:1fr}.tx-row .tx-amount{text-align:left}.folio-row .folio-values{grid-template-columns:1fr}}
</style>

<script>
document.addEventListener('DOMContentLoaded', function () {
    const modalEl = document.getElementById('folioBalanceModal');
    const modal = modalEl && window.bootstrap ? new bootstrap.Modal(modalEl) : null;
    let activeFolios = {master: [], room: [], guest: [], other: [], all: []};
    let activeOrderId = '';

    function money(value) {
        const num = parseFloat(value || '0') || 0;
        return num.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2});
    }

    function escapeHtml(value) {
        return String(value || '').replace(/[&<>'"]/g, function (ch) {
            return {'&':'&amp;','<':'&lt;','>':'&gt;',"'":'&#039;','"':'&quot;'}[ch] || ch;
        });
    }

    function proformaUrl(type, orderId, folioId) {
        if (type === 'master') return '/rooms/modules/payments/proforma_master_folio.php?order_id=' + encodeURIComponent(orderId);
        if (type === 'room') return '/rooms/modules/payments/proforma_room_account.php?order_id=' + encodeURIComponent(orderId) + (folioId ? '&folio_id=' + encodeURIComponent(folioId) : '');
        if (type === 'guest') return '/rooms/modules/payments/proforma_guest_folio.php?order_id=' + encodeURIComponent(orderId) + (folioId ? '&folio_id=' + encodeURIComponent(folioId) : '');
        return '/rooms/modules/payments/proforma_invoice.php?order_id=' + encodeURIComponent(orderId);
    }

    function txRows(rows, group) {
        rows = Array.isArray(rows) ? rows : [];
        if (!rows.length) return '<div class="tx-empty">No ' + group + ' found on this folio.</div>';
        return rows.map(row => {
            const debit = parseFloat(row.debit || '0') || 0;
            const credit = parseFloat(row.credit || '0') || 0;
            const amount = credit > 0 ? credit : debit;
            const isPayment = credit > 0;
            const isVoid = parseInt(row.is_voided || '0', 10) === 1;
            const desc = row.display_description || row.description || row.tx_type || 'Transaction';
            const category = row.charge_category || '';
            const label = desc + ' #' + (row.id || '');
            return `
                <div class="tx-row ${isPayment ? 'is-payment' : 'is-charge'} ${isVoid ? 'is-void' : ''}">
                    <div>${escapeHtml((row.tx_date || '').substring(0,10))}</div>
                    <div class="tx-desc"><strong>${escapeHtml(desc)}</strong><small>${category ? escapeHtml(category) + ' • ' : ''}${escapeHtml(row.tx_type || '')} ${row.source_table ? '• ' + escapeHtml(row.source_table) : ''}</small></div>
                    <div class="tx-amount">${money(amount)}</div>
                    <div class="text-end"><button type="button" class="btn btn-sm btn-outline-dark select-move-btn" data-tx-id="${escapeHtml(row.id)}" data-label="${escapeHtml(label)}">Move</button></div>
                </div>
            `;
        }).join('');
    }

    function folioRow(row, type) {
        const balance = parseFloat(row.balance || '0') || 0;
        const balanceClass = Math.abs(balance) > 0.00001 ? 'folio-balance-positive' : 'folio-balance-zero';
        const label = row.display_label || row.folio_no || ('Folio #' + (row.id || ''));
        const tx = row.transactions || {charges: [], payments: [], other: []};
        return `
            <details class="folio-row">
                <summary>
                    <div class="folio-label"><span>${escapeHtml(label)}</span><span class="badge text-bg-light border">#${escapeHtml(row.id)}</span></div>
                    <div class="folio-values">
                        <span>Charges<strong>${money(row.total_charges)}</strong></span>
                        <span>Payments<strong>${money(row.total_payments)}</strong></span>
                        <span>Balance<strong class="${balanceClass}">${money(row.balance)}</strong></span>
                    </div>
                    <div class="folio-tools">
                        <a class="btn btn-outline-danger" target="_blank" rel="noopener" href="${proformaUrl(type, activeOrderId, row.id)}"><i class="bi bi-file-earmark-pdf me-1"></i>Print Proforma</a>
                    </div>
                </summary>
                <div class="tx-tree">
                    <div class="tx-group-title">Charges</div>
                    ${txRows(tx.charges, 'charges')}
                    <div class="tx-group-title">Payments</div>
                    ${txRows(tx.payments, 'payments')}
                    ${tx.other && tx.other.length ? '<div class="tx-group-title">Other</div>' + txRows(tx.other, 'transactions') : ''}
                </div>
            </details>
        `;
    }

    function renderList(targetId, rows, type) {
        const el = document.getElementById(targetId);
        if (!el) return;
        rows = Array.isArray(rows) ? rows : [];
        if (!rows.length) {
            el.innerHTML = '<div class="folio-empty">No active folio found.</div>';
            return;
        }
        el.innerHTML = rows.map(row => folioRow(row, type)).join('');
    }

    function populateMoveTargets(selectedTxId) {
        const select = document.getElementById('moveTargetFolio');
        if (!select) return;
        const all = Array.isArray(activeFolios.all) ? activeFolios.all : [];
        select.innerHTML = '<option value="">Select destination folio</option>' + all.map(f => `<option value="${escapeHtml(f.id)}">${escapeHtml((f.type || '').toUpperCase())} • ${escapeHtml(f.label || ('Folio #' + f.id))} • Bal ${money(f.balance)}</option>`).join('');
    }

    function openMovePanel(txId, label) {
        document.getElementById('moveTransactionId').value = txId || '';
        document.getElementById('moveTransactionLabel').value = label || ('Transaction #' + txId);
        populateMoveTargets(txId);
        document.getElementById('movePanel').style.display = '';
        document.getElementById('movePanel').scrollIntoView({behavior:'smooth', block:'center'});
    }

    function renderBreakdownGrid(breakdown) {
        const el = document.getElementById('folioBreakdownGrid');
        if (!el) return;
        breakdown = breakdown || {};
        const cards = [
            ['Accommodation', breakdown.accommodation || 0],
            ['Restaurant', breakdown.restaurant || 0],
            ['Bar', breakdown.bar || 0],
            ['Spa', breakdown.spa || 0],
            ['Curio', breakdown.curio || 0],
            ['Other Extras', breakdown.extras || 0],
            ['Payments', breakdown.payments || 0],
            ['Voided', breakdown.voided || 0],
        ];
        el.innerHTML = cards.map(([label, value]) => `
            <div class="folio-breakdown-pill">
                <span>${escapeHtml(label)}</span>
                <strong>${money(value)}</strong>
            </div>
        `).join('');
    }

    function openFolioModal(row) {
        if (!row || !modal) return;
        let folios = {master: [], room: [], guest: [], other: [], all: []};
        try { folios = JSON.parse(row.dataset.folios || '{}') || folios; } catch (e) {}
        let breakdown = {};
        try { breakdown = JSON.parse(row.dataset.breakdown || '{}') || {}; } catch (e) {}
        activeFolios = folios;

        const orderId = row.dataset.orderId || '';
        activeOrderId = orderId;
        const booking = row.dataset.booking || '-';
        const guest = row.dataset.guest || '-';
        const rooms = row.dataset.rooms || '-';
        const property = row.dataset.property || '-';
        const balance = row.dataset.balance || '0.00';

        document.getElementById('folioModalBooking').textContent = booking;
        document.getElementById('folioModalGuest').textContent = guest;
        document.getElementById('folioModalRooms').textContent = rooms;
        document.getElementById('folioModalBalance').textContent = balance;
        document.getElementById('folioModalSubtitle').textContent = property;
        renderBreakdownGrid(breakdown);

        document.getElementById('folioPrintFull').href = proformaUrl('full', orderId, '');
        document.getElementById('folioPrintMaster').href = proformaUrl('master', orderId, '');
        document.getElementById('folioPrintRoom').href = proformaUrl('room', orderId, '');
        document.getElementById('folioPrintGuest').href = '/rooms/modules/payments/guest_folios.php?order_id=' + encodeURIComponent(orderId);

        renderList('folioMasterList', folios.master || [], 'master');
        renderList('folioRoomList', folios.room || [], 'room');
        renderList('folioGuestList', folios.guest || [], 'guest');

        const otherWrap = document.getElementById('folioOtherWrap');
        if (folios.other && folios.other.length) {
            renderList('folioOtherList', folios.other, 'other');
            otherWrap.style.display = '';
        } else if (otherWrap) {
            otherWrap.style.display = 'none';
        }

        const movePanel = document.getElementById('movePanel');
        if (movePanel) movePanel.style.display = 'none';

        const paymentsLink = document.getElementById('folioModalPaymentsLink');
        const foliosLink = document.getElementById('folioModalFoliosLink');
        if (paymentsLink) paymentsLink.href = '/rooms/modules/payments/payments.php?order_id=' + encodeURIComponent(orderId);
        if (foliosLink) foliosLink.href = '/rooms/modules/payments/folio.php?q=' + encodeURIComponent(booking);

        modal.show();
    }

    document.querySelectorAll('.booking-folio-row').forEach(function (row) {
        row.addEventListener('dblclick', function (e) {
            if (e.target.closest('a,button,form,.dropdown')) return;
            openFolioModal(row);
        });
    });

    document.querySelectorAll('.view-folio-summary').forEach(function (btn) {
        btn.addEventListener('click', function () {
            const row = document.querySelector('.booking-folio-row[data-order-id="' + this.dataset.orderId + '"]');
            openFolioModal(row);
        });
    });

    document.addEventListener('click', function(e){
        const btn = e.target.closest('.select-move-btn');
        if (!btn) return;
        openMovePanel(btn.dataset.txId || '', btn.dataset.label || '');
    });
});
</script>

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