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

$pageTitle = 'Restaurant Reservation';

if (!function_exists('h')) {
    function h($v): string { return htmlspecialchars((string)$v, ENT_QUOTES, 'UTF-8'); }
}
if (!function_exists('rr_flash')) {
    function rr_flash(string $type, string $message): void {
        $_SESSION['restaurant_reservation_flash'][] = ['type' => $type, 'message' => $message];
    }
    function rr_get_flash(): array {
        $x = $_SESSION['restaurant_reservation_flash'] ?? [];
        unset($_SESSION['restaurant_reservation_flash']);
        return $x;
    }
}
if (!function_exists('rr_current_user_id')) {
    function rr_current_user_id(): ?int {
        foreach (['user_id','ss_user_id','id','uid'] as $k) {
            if (isset($_SESSION[$k]) && (int)$_SESSION[$k] > 0) return (int)$_SESSION[$k];
        }
        return null;
    }
}
if (!function_exists('rr_current_user_name')) {
    function rr_current_user_name(): string {
        foreach (['currentUserName','current_user_name','user_name','username','full_name','name'] as $k) {
            if (isset($_SESSION[$k]) && trim((string)$_SESSION[$k]) !== '') return trim((string)$_SESSION[$k]);
        }
        return 'Logged user';
    }
}
if (!function_exists('rr_table_exists')) {
    function rr_table_exists(PDO $pdo, string $table): bool {
        static $cache = [];
        if (array_key_exists($table, $cache)) return $cache[$table];
        try {
            $s = $pdo->prepare("SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = :t");
            $s->execute([':t' => $table]);
            return $cache[$table] = ((int)$s->fetchColumn() > 0);
        } catch (Throwable $e) { return $cache[$table] = false; }
    }
}
if (!function_exists('rr_column_exists')) {
    function rr_column_exists(PDO $pdo, string $table, string $column): bool {
        static $cache = [];
        $key = $table.'.'.$column;
        if (array_key_exists($key, $cache)) return $cache[$key];
        try {
            $s = $pdo->prepare("SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = :t AND column_name = :c");
            $s->execute([':t' => $table, ':c' => $column]);
            return $cache[$key] = ((int)$s->fetchColumn() > 0);
        } catch (Throwable $e) { return $cache[$key] = false; }
    }
}
if (!function_exists('rr_order_no')) {
    function rr_order_no(PDO $pdo): string {
        $p = 'RST-' . date('ymd') . '-';
        $s = $pdo->prepare("SELECT COUNT(*) FROM restaurant_orders WHERE order_no LIKE :p");
        $s->execute([':p' => $p.'%']);
        return $p . str_pad((string)((int)$s->fetchColumn() + 1), 4, '0', STR_PAD_LEFT);
    }
}
if (!function_exists('rr_has_table_conflict')) {
    function rr_has_table_conflict(PDO $pdo, int $tableId, string $date, string $time, int $duration, int $excludeId = 0): bool {
        if ($tableId <= 0) return false;
        $stmt = $pdo->prepare("\n            SELECT COUNT(*)\n            FROM restaurant_reservations\n            WHERE table_id = :table_id\n              AND reservation_date = :reservation_date\n              AND status IN ('booked','seated')\n              AND id <> :exclude_id\n              AND (\n                    reservation_time < ADDTIME(:new_time, SEC_TO_TIME(:duration_minutes * 60))\n                AND ADDTIME(reservation_time, SEC_TO_TIME(duration_minutes * 60)) > :new_time\n              )\n        ");
        $stmt->execute([
            ':table_id' => $tableId,
            ':reservation_date' => $date,
            ':new_time' => $time,
            ':duration_minutes' => $duration,
            ':exclude_id' => $excludeId,
        ]);
        return (int)$stmt->fetchColumn() > 0;
    }
}

if (!function_exists('rr_csv_ids')) {
    function rr_csv_ids(array $ids): string {
        $clean = [];
        foreach ($ids as $id) {
            $id = (int)$id;
            if ($id > 0) $clean[$id] = $id;
        }
        return implode(',', array_values($clean));
    }
}
if (!function_exists('rr_parse_csv_ids')) {
    function rr_parse_csv_ids($csv): array {
        if ($csv === null || $csv === '') return [];
        $out = [];
        foreach (preg_split('/\s*,\s*/', (string)$csv) as $id) {
            $id = (int)$id;
            if ($id > 0) $out[$id] = $id;
        }
        return array_values($out);
    }
}
if (!function_exists('rr_table_ids_from_post')) {
    function rr_table_ids_from_post(): array {
        $ids = $_POST['table_ids'] ?? [];
        if (!is_array($ids)) $ids = [$ids];
        $single = (int)($_POST['table_id'] ?? 0);
        if ($single > 0) $ids[] = $single;
        $clean = [];
        foreach ($ids as $id) {
            $id = (int)$id;
            if ($id > 0) $clean[$id] = $id;
        }
        return array_values($clean);
    }
}
if (!function_exists('rr_fetch_tables_meta')) {
    function rr_fetch_tables_meta(PDO $pdo, array $tableIds): array {
        $tableIds = array_values(array_unique(array_map('intval', $tableIds)));
        $tableIds = array_filter($tableIds, fn($id) => $id > 0);
        if (!$tableIds) return [];
        $in = implode(',', array_fill(0, count($tableIds), '?'));
        $stmt = $pdo->prepare("
            SELECT t.*, a.area_name
            FROM restaurant_tables t
            LEFT JOIN restaurant_areas a ON a.id = t.area_id
            WHERE t.id IN ($in) AND t.is_active = 1
            ORDER BY a.sort_order, t.table_no
        ");
        $stmt->execute($tableIds);
        return $stmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
    }
}
if (!function_exists('rr_tables_label')) {
    function rr_tables_label(array $tableRows): string {
        $labels = [];
        foreach ($tableRows as $t) {
            $labels[] = trim('Table ' . (string)($t['table_no'] ?? ''));
        }
        return implode(' + ', array_filter($labels));
    }
}
if (!function_exists('rr_tables_capacity')) {
    function rr_tables_capacity(array $tableRows): int {
        $seats = 0;
        foreach ($tableRows as $t) $seats += max(0, (int)($t['seats'] ?? 0));
        return $seats;
    }
}
if (!function_exists('rr_reservation_table_ids')) {
    function rr_reservation_table_ids(array $reservation): array {
        $ids = rr_parse_csv_ids($reservation['merged_table_ids'] ?? '');
        $primary = (int)($reservation['table_id'] ?? 0);
        if ($primary > 0) $ids[$primary] = $primary;
        return array_values(array_unique(array_map('intval', $ids)));
    }
}
if (!function_exists('rr_validate_table_combo')) {
    function rr_validate_table_combo(PDO $pdo, array $tableIds, int $covers, string $date, string $time, int $duration, int $excludeReservationId = 0): array {
        if (!$tableIds) {
            return ['primary_table_id' => null, 'merged_table_ids' => '', 'capacity' => 0, 'label' => 'Allocate later', 'rows' => []];
        }
        $tableRows = rr_fetch_tables_meta($pdo, $tableIds);
        if (count($tableRows) !== count(array_unique($tableIds))) {
            throw new RuntimeException('One or more selected tables were not found or are inactive.');
        }
        $capacity = rr_tables_capacity($tableRows);
        if ($covers > $capacity) {
            throw new RuntimeException('Covers exceed combined table capacity of ' . $capacity . ' seats.');
        }
        $selectedSet = array_fill_keys(array_map('intval', $tableIds), true);
        $stmt = $pdo->prepare("
            SELECT id, table_id, merged_table_ids, guest_name, reservation_time, duration_minutes
            FROM restaurant_reservations
            WHERE reservation_date = :reservation_date
              AND status IN ('booked','seated')
              AND id <> :id
              AND (
                  reservation_time < ADDTIME(:new_time, SEC_TO_TIME(:duration * 60))
                  AND ADDTIME(reservation_time, SEC_TO_TIME(duration_minutes * 60)) > :new_time
              )
        ");
        $stmt->execute([
            ':reservation_date' => $date,
            ':new_time' => $time,
            ':duration' => $duration,
            ':id' => $excludeReservationId,
        ]);
        while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
            $existingIds = rr_reservation_table_ids($row);
            foreach ($existingIds as $existingId) {
                if (isset($selectedSet[(int)$existingId])) {
                    throw new RuntimeException('Table already reserved during this time window by ' . trim((string)($row['guest_name'] ?? 'another booking')) . '.');
                }
            }
        }
        $primary = (int)$tableIds[0];
        return [
            'primary_table_id' => $primary,
            'merged_table_ids' => rr_csv_ids($tableIds),
            'capacity' => $capacity,
            'label' => rr_tables_label($tableRows),
            'rows' => $tableRows,
        ];
    }
}

$errors = [];

try {
    $pdo->exec("CREATE TABLE IF NOT EXISTS restaurant_reservations (
        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        property_id INT UNSIGNED NULL,
        restaurant_area_id INT UNSIGNED NULL,
        table_id INT UNSIGNED NULL,
        order_id INT UNSIGNED NULL,
        guest_id INT UNSIGNED NULL,
        room_no VARCHAR(80) NULL,
        guest_name VARCHAR(180) NOT NULL,
        reservation_date DATE NOT NULL,
        reservation_time TIME NOT NULL,
        duration_minutes INT UNSIGNED NOT NULL DEFAULT 90,
        covers INT UNSIGNED NOT NULL DEFAULT 1,
        meal_period ENUM('breakfast','lunch','dinner','other') NOT NULL DEFAULT 'dinner',
        source ENUM('room_guest','walkin','external') NOT NULL DEFAULT 'room_guest',
        status ENUM('booked','seated','no_show','cancelled','completed') NOT NULL DEFAULT 'booked',
        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,
        INDEX idx_rest_res_date_time (reservation_date, reservation_time),
        INDEX idx_rest_res_table (table_id, reservation_date, reservation_time),
        INDEX idx_rest_res_order (order_id),
        INDEX idx_rest_res_status (status)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    $pdo->exec("CREATE TABLE IF NOT EXISTS restaurant_orders (
        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        property_id INT UNSIGNED NULL,
        area_id INT UNSIGNED NULL,
        table_id INT UNSIGNED NULL,
        order_no VARCHAR(60) NOT NULL,
        order_type ENUM('table','room','walkin','takeaway') NOT NULL DEFAULT 'table',
        linked_order_id INT UNSIGNED NULL,
        linked_folio_id INT UNSIGNED NULL,
        guest_name VARCHAR(180) NULL,
        room_no VARCHAR(80) NULL,
        covers INT UNSIGNED NOT NULL DEFAULT 1,
        status ENUM('open','sent','closed','void') NOT NULL DEFAULT 'open',
        subtotal DECIMAL(14,2) NOT NULL DEFAULT 0.00,
        tax_total DECIMAL(14,2) NOT NULL DEFAULT 0.00,
        total_amount DECIMAL(14,2) NOT NULL DEFAULT 0.00,
        payment_status ENUM('unpaid','part_paid','paid','room_charged','void') NOT NULL DEFAULT 'unpaid',
        opened_by INT UNSIGNED NULL,
        closed_by INT UNSIGNED NULL,
        opened_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
        closed_at DATETIME NULL,
        notes TEXT NULL,
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        UNIQUE KEY uq_rest_order_no(order_no),
        INDEX idx_rest_order_table_status(table_id,status)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    if (!rr_column_exists($pdo, 'restaurant_orders', 'room_no')) {
        $pdo->exec("ALTER TABLE restaurant_orders ADD COLUMN room_no VARCHAR(80) NULL AFTER guest_name");
    }
    $resCols = [
        'merged_table_ids' => "ALTER TABLE restaurant_reservations ADD COLUMN merged_table_ids VARCHAR(255) NULL AFTER table_id",
        'merged_capacity'  => "ALTER TABLE restaurant_reservations ADD COLUMN merged_capacity INT UNSIGNED NOT NULL DEFAULT 0 AFTER merged_table_ids",
    ];
    foreach ($resCols as $col => $ddl) {
        if (!rr_column_exists($pdo, 'restaurant_reservations', $col)) $pdo->exec($ddl);
    }
    $ordCols = [
        'merged_table_ids' => "ALTER TABLE restaurant_orders ADD COLUMN merged_table_ids VARCHAR(255) NULL AFTER table_id",
        'merged_capacity'  => "ALTER TABLE restaurant_orders ADD COLUMN merged_capacity INT UNSIGNED NOT NULL DEFAULT 0 AFTER merged_table_ids",
    ];
    foreach ($ordCols as $col => $ddl) {
        if (!rr_column_exists($pdo, 'restaurant_orders', $col)) $pdo->exec($ddl);
    }
} catch (Throwable $e) {
    $errors[] = 'Could not prepare restaurant reservation tables: ' . $e->getMessage();
}

$id = (int)($_GET['id'] ?? $_POST['id'] ?? 0);
$form = [
    'id' => 0,
    'property_id' => '',
    'restaurant_area_id' => '',
    'table_id' => '',
    'merged_table_ids' => '',
    'merged_capacity' => 0,
    'order_id' => '',
    'guest_id' => '',
    'room_no' => '',
    'guest_name' => '',
    'reservation_date' => date('Y-m-d'),
    'reservation_time' => '19:00',
    'duration_minutes' => 90,
    'covers' => 2,
    'meal_period' => 'dinner',
    'source' => 'room_guest',
    'status' => 'booked',
    'notes' => '',
];

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $form = array_merge($form, $_POST);
}

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

        $action = (string)($_POST['action'] ?? 'save');
        $id = (int)($_POST['id'] ?? 0);

        if (in_array($action, ['cancel','no_show','complete'], true)) {
            if ($id <= 0) throw new RuntimeException('Invalid reservation selected.');
            $newStatus = $action === 'cancel' ? 'cancelled' : ($action === 'no_show' ? 'no_show' : 'completed');
            $stmt = $pdo->prepare("UPDATE restaurant_reservations SET status = :status WHERE id = :id");
            $stmt->execute([':status' => $newStatus, ':id' => $id]);
            rr_flash('success', 'Reservation marked as ' . str_replace('_', ' ', $newStatus) . '.');
            header('Location: reservations.php');
            exit;
        }

        if ($action === 'seat') {
            if ($id <= 0) throw new RuntimeException('Invalid reservation selected.');
            $stmt = $pdo->prepare("SELECT * FROM restaurant_reservations WHERE id = :id LIMIT 1");
            $stmt->execute([':id' => $id]);
            $res = $stmt->fetch(PDO::FETCH_ASSOC);
            if (!$res) throw new RuntimeException('Reservation not found.');
            if (!in_array((string)$res['status'], ['booked','seated'], true)) throw new RuntimeException('Only booked reservations can be seated.');
            $seatTableIds = rr_reservation_table_ids($res);
            if (!$seatTableIds) throw new RuntimeException('Please allocate at least one table before seating the guest.');

            $in = implode(',', array_fill(0, count($seatTableIds), '?'));
            $openSql = "
                SELECT id
                FROM restaurant_orders
                WHERE status IN ('open','sent')
                  AND (table_id IN ($in)";
            $openParams = $seatTableIds;
            if (rr_column_exists($pdo, 'restaurant_orders', 'merged_table_ids')) {
                $openSql .= ' OR ' . implode(' OR ', array_fill(0, count($seatTableIds), 'FIND_IN_SET(?, merged_table_ids)'));
                $openParams = array_merge($openParams, $seatTableIds);
            }
            $openSql .= ') LIMIT 1';
            $openStmt = $pdo->prepare($openSql);
            $openStmt->execute($openParams);
            $restaurantOrderId = (int)$openStmt->fetchColumn();

            if ($restaurantOrderId <= 0) {
                $ins = $pdo->prepare("
                    INSERT INTO restaurant_orders
                    (property_id, area_id, table_id, merged_table_ids, merged_capacity, order_no, order_type, linked_order_id, guest_name, room_no, covers, status, opened_by, notes)
                    VALUES
                    (:property_id, :area_id, :table_id, :merged_table_ids, :merged_capacity, :order_no, :order_type, :linked_order_id, :guest_name, :room_no, :covers, 'open', :opened_by, :notes)
                ");
                $ins->execute([
                    ':property_id' => $res['property_id'] ?: null,
                    ':area_id' => $res['restaurant_area_id'] ?: null,
                    ':table_id' => (int)$seatTableIds[0],
                    ':merged_table_ids' => rr_csv_ids($seatTableIds),
                    ':merged_capacity' => (int)($res['merged_capacity'] ?? 0),
                    ':order_no' => rr_order_no($pdo),
                    ':order_type' => $res['source'] === 'room_guest' ? 'room' : 'walkin',
                    ':linked_order_id' => $res['source'] === 'room_guest' ? ($res['order_id'] ?: null) : null,
                    ':guest_name' => $res['guest_name'],
                    ':room_no' => $res['source'] === 'room_guest' ? ($res['room_no'] ?: null) : null,
                    ':covers' => max(1, (int)$res['covers']),
                    ':opened_by' => rr_current_user_id(),
                    ':notes' => 'Opened from restaurant reservation #' . (int)$res['id'],
                ]);
                $restaurantOrderId = (int)$pdo->lastInsertId();
                $updIn = implode(',', array_fill(0, count($seatTableIds), '?'));
                $upd = $pdo->prepare("UPDATE restaurant_tables SET status = 'occupied' WHERE id IN ($updIn)");
                $upd->execute($seatTableIds);
            }

            $pdo->prepare("UPDATE restaurant_reservations SET status = 'seated' WHERE id = :id")->execute([':id' => $id]);
            rr_flash('success', 'Guest seated and restaurant order opened.');
            header('Location: planner.php?restaurant_order_id=' . $restaurantOrderId);
            exit;
        }

        $source = (string)($_POST['source'] ?? 'room_guest');
        if (!in_array($source, ['room_guest','walkin','external'], true)) $source = 'room_guest';

        $propertyId = (int)($_POST['property_id'] ?? 0);
        $areaId = (int)($_POST['restaurant_area_id'] ?? 0);
        $tableIds = rr_table_ids_from_post();
        $tableId = $tableIds ? (int)$tableIds[0] : 0;
        $orderId = (int)($_POST['order_id'] ?? 0);
        $guestId = (int)($_POST['guest_id'] ?? 0);
        $guestName = trim((string)($_POST['guest_name'] ?? ''));
        $roomNo = trim((string)($_POST['room_no'] ?? ''));
        $date = trim((string)($_POST['reservation_date'] ?? ''));
        $time = trim((string)($_POST['reservation_time'] ?? ''));
        $duration = max(15, (int)($_POST['duration_minutes'] ?? 90));
        $covers = max(1, (int)($_POST['covers'] ?? 1));
        $mealPeriod = (string)($_POST['meal_period'] ?? 'dinner');
        $status = (string)($_POST['status'] ?? 'booked');
        $notes = trim((string)($_POST['notes'] ?? ''));

        if (!in_array($mealPeriod, ['breakfast','lunch','dinner','other'], true)) $mealPeriod = 'dinner';
        if (!in_array($status, ['booked','seated','no_show','cancelled','completed'], true)) $status = 'booked';
        if ($date === '' || strtotime($date) === false) throw new RuntimeException('Please select a valid reservation date.');
        if ($time === '' || strtotime($time) === false) throw new RuntimeException('Please select a valid reservation time.');
        $time = date('H:i:s', strtotime($time));

        if ($source === 'room_guest') {
            if ($orderId <= 0) throw new RuntimeException('Please select an in-house guest / room booking.');
            if ($guestName === '') throw new RuntimeException('Guest name could not be resolved. Please select the guest again.');
        } else {
            if ($guestName === '') $guestName = $source === 'walkin' ? 'Direct Sale' : 'External Guest';
            $orderId = 0; $guestId = 0; $roomNo = '';
        }

        $tableCombo = ['primary_table_id' => $tableId > 0 ? $tableId : null, 'merged_table_ids' => '', 'capacity' => 0];
        if (in_array($status, ['booked','seated'], true)) {
            $tableCombo = rr_validate_table_combo($pdo, $tableIds, $covers, $date, $time, $duration, $id);
        } elseif ($tableIds) {
            $rows = rr_fetch_tables_meta($pdo, $tableIds);
            $tableCombo = [
                'primary_table_id' => $tableIds[0],
                'merged_table_ids' => rr_csv_ids($tableIds),
                'capacity' => rr_tables_capacity($rows),
            ];
        }
        $tableId = (int)($tableCombo['primary_table_id'] ?? 0);

        $data = [
            ':property_id' => $propertyId > 0 ? $propertyId : null,
            ':restaurant_area_id' => $areaId > 0 ? $areaId : null,
            ':table_id' => $tableId > 0 ? $tableId : null,
            ':merged_table_ids' => (string)($tableCombo['merged_table_ids'] ?? ''),
            ':merged_capacity' => (int)($tableCombo['capacity'] ?? 0),
            ':order_id' => $orderId > 0 ? $orderId : null,
            ':guest_id' => $guestId > 0 ? $guestId : null,
            ':room_no' => $roomNo !== '' ? $roomNo : null,
            ':guest_name' => $guestName,
            ':reservation_date' => $date,
            ':reservation_time' => $time,
            ':duration_minutes' => $duration,
            ':covers' => $covers,
            ':meal_period' => $mealPeriod,
            ':source' => $source,
            ':status' => $status,
            ':notes' => $notes !== '' ? $notes : null,
        ];

        if ($id > 0) {
            $data[':id'] = $id;
            $stmt = $pdo->prepare("\n                UPDATE restaurant_reservations\n                SET property_id=:property_id, restaurant_area_id=:restaurant_area_id, table_id=:table_id, merged_table_ids=:merged_table_ids, merged_capacity=:merged_capacity, order_id=:order_id, guest_id=:guest_id, room_no=:room_no, guest_name=:guest_name, reservation_date=:reservation_date, reservation_time=:reservation_time, duration_minutes=:duration_minutes, covers=:covers, meal_period=:meal_period, source=:source, status=:status, notes=:notes\n                WHERE id=:id\n            ");
            $stmt->execute($data);
            rr_flash('success', 'Restaurant reservation updated.');
        } else {
            $data[':created_by'] = rr_current_user_id();
            $stmt = $pdo->prepare("\n                INSERT INTO restaurant_reservations\n                (property_id, restaurant_area_id, table_id, merged_table_ids, merged_capacity, order_id, guest_id, room_no, guest_name, reservation_date, reservation_time, duration_minutes, covers, meal_period, source, status, notes, created_by)\n                VALUES\n                (:property_id, :restaurant_area_id, :table_id, :merged_table_ids, :merged_capacity, :order_id, :guest_id, :room_no, :guest_name, :reservation_date, :reservation_time, :duration_minutes, :covers, :meal_period, :source, :status, :notes, :created_by)\n            ");
            $stmt->execute($data);
            $id = (int)$pdo->lastInsertId();
            rr_flash('success', 'Restaurant reservation created.');
        }
        header('Location: reservation_form.php?id=' . $id);
        exit;
    } catch (Throwable $e) {
        $errors[] = $e->getMessage();
        $form = array_merge($form, $_POST);
    }
}

if ($_SERVER['REQUEST_METHOD'] !== 'POST' && $id > 0) {
    try {
        $stmt = $pdo->prepare("SELECT * FROM restaurant_reservations WHERE id = :id LIMIT 1");
        $stmt->execute([':id' => $id]);
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        if ($row) {
            $form = array_merge($form, $row);
            $form['reservation_time'] = substr((string)($form['reservation_time'] ?? '19:00'), 0, 5);
        } else {
            $errors[] = 'Restaurant reservation not found.';
        }
    } catch (Throwable $e) { $errors[] = $e->getMessage(); }
}

$flashes = rr_get_flash();
$properties = [];$areas = [];$tables = [];$inhouseGuests = [];$availability = [];
try {
    if (rr_table_exists($pdo, 'properties')) {
        $propsSql = rr_column_exists($pdo, 'properties', 'is_active') ? "SELECT id, name FROM properties WHERE is_active=1 ORDER BY name" : "SELECT id, name FROM properties ORDER BY name";
        $properties = $pdo->query($propsSql)->fetchAll(PDO::FETCH_ASSOC);
    }
} catch (Throwable $e) {}
try { $areas = $pdo->query("SELECT * FROM restaurant_areas WHERE is_active = 1 ORDER BY sort_order, area_name")->fetchAll(PDO::FETCH_ASSOC); } catch (Throwable $e) {}
try {
    $tables = $pdo->query("\n        SELECT t.*, a.area_name\n        FROM restaurant_tables t\n        LEFT JOIN restaurant_areas a ON a.id = t.area_id\n        WHERE t.is_active = 1 AND t.status <> 'blocked'\n        ORDER BY a.sort_order, t.table_no\n    ")->fetchAll(PDO::FETCH_ASSOC);
} catch (Throwable $e) {}
try {
    $inhouseGuests = $pdo->query("\n        SELECT o.id AS order_id, o.property_id, CAST(o.guest_id AS UNSIGNED) AS guest_id, o.order_no,\n               TRIM(CONCAT(COALESCE(g.firstname,''), ' ', COALESCE(g.lastname,''))) AS guest_name,\n               COALESCE(orx.room_no, rm.room_no, '') AS room_no,\n               COALESCE(orx.check_in, o.check_in) AS check_in,\n               COALESCE(orx.check_out, o.check_out) AS check_out,\n               p.name AS property_name\n        FROM orders o\n        LEFT JOIN guests g ON g.id = CAST(o.guest_id AS UNSIGNED)\n        LEFT JOIN order_rooming orx ON orx.order_id = o.id\n        LEFT JOIN rooms rm ON rm.id = orx.room_id\n        LEFT JOIN properties p ON p.id = o.property_id\n        WHERE COALESCE(o.status,1) NOT IN (0,4)\n          AND DATE(COALESCE(orx.check_in, o.check_in)) <= CURDATE()\n          AND DATE(COALESCE(orx.check_out, o.check_out)) > CURDATE()\n        GROUP BY o.id, orx.room_no, rm.room_no\n        ORDER BY room_no ASC, guest_name ASC\n        LIMIT 400\n    ")->fetchAll(PDO::FETCH_ASSOC);
} catch (Throwable $e) { $inhouseGuests = []; }
try {
    $dateForAvailability = $form['reservation_date'] ?: date('Y-m-d');
    $stmt = $pdo->prepare("\n        SELECT table_id, COUNT(*) AS reservations_count\n        FROM restaurant_reservations\n        WHERE reservation_date = :reservation_date AND status IN ('booked','seated') AND table_id IS NOT NULL\n        GROUP BY table_id\n    ");
    $stmt->execute([':reservation_date' => $dateForAvailability]);
    foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $r) $availability[(int)$r['table_id']] = (int)$r['reservations_count'];
} catch (Throwable $e) {}


$editTableIds = rr_parse_csv_ids($form['merged_table_ids'] ?? '');
if (!$editTableIds && (int)($form['table_id'] ?? 0) > 0) {
    $editTableIds = [(int)$form['table_id']];
}
$editTableIdSet = array_fill_keys($editTableIds, true);
$selectedSource = (string)($form['source'] ?? 'room_guest');
$isRoomGuestSource = $selectedSource === 'room_guest';
require_once __DIR__ . '/../../includes/header.php';
?>

<div class="hero-band compact-restaurant-hero">
    <div class="row align-items-center g-2">
        <div class="col-lg-7">
            <div class="page-eyebrow text-white-50"><i class="bi bi-calendar-plus"></i> Restaurant</div>
            <div class="hero-title mt-1"><?php echo $id > 0 ? 'Edit Restaurant Reservation' : 'New Restaurant Reservation'; ?></div>
            <div class="hero-subtitle mt-1">Book restaurant tables for in-house guests, walk-ins, or outside customers.</div>
        </div>
        <div class="col-lg-5 text-lg-end">
            <a href="reservations.php" class="btn btn-outline-light btn-sm"><i class="bi bi-list-ul me-1"></i>Reservations</a>
            <a href="planner.php" class="btn btn-light btn-sm"><i class="bi bi-grid-3x3-gap me-1"></i>Planner</a>
            <a href="restaurant_tables.php" class="btn btn-warning btn-sm"><i class="bi bi-table me-1"></i>Tables</a>
        </div>
    </div>
</div>

<?php foreach ($flashes as $f): ?><div class="alert alert-<?php echo h($f['type']); ?>"><?php echo h($f['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; ?>

<div class="row g-3">
    <div class="col-xl-8">
        <div class="card panel-card">
            <div class="card-header d-flex align-items-center justify-content-between">
                <h5 class="mb-0">Reservation Details</h5>
                <span class="badge text-bg-light border">Created by <?php echo h(rr_current_user_name()); ?></span>
            </div>
            <div class="card-body">
                <form method="post" id="reservationForm" class="row g-3">
                    <?php if (function_exists('csrf_field')) echo csrf_field(); ?>
                    <input type="hidden" name="action" value="save">
                    <input type="hidden" name="id" value="<?php echo (int)($form['id'] ?? 0); ?>">
                    <input type="hidden" name="guest_id" id="guest_id" value="<?php echo h($form['guest_id'] ?? ''); ?>">
                    <input type="hidden" name="room_no" id="room_no_hidden" value="<?php echo h($form['room_no'] ?? ''); ?>">

                    <div class="col-md-3">
                        <label class="form-label">Source</label>
                        <select name="source" id="source" class="form-select" required>
                            <?php foreach (['room_guest'=>'Room Guest','walkin'=>'Walk-in','external'=>'External'] as $value => $label): ?>
                                <option value="<?php echo h($value); ?>" <?php echo ($form['source'] ?? '') === $value ? 'selected' : ''; ?>><?php echo h($label); ?></option>
                            <?php endforeach; ?>
                        </select>
                    </div>
                    <div class="col-md-5 room-guest-field">
                        <label class="form-label">In-house Guest / Room</label>
                        <select name="order_id" id="order_id" class="form-select">
                            <option value="">Select in-house guest</option>
                            <?php foreach ($inhouseGuests as $g): ?>
                                <?php $guestLabel = trim((string)($g['guest_name'] ?? '')); if ($guestLabel === '') $guestLabel = 'Guest'; $room = trim((string)($g['room_no'] ?? '')); $selected = (int)($form['order_id'] ?? 0) === (int)$g['order_id']; ?>
                                <option value="<?php echo (int)$g['order_id']; ?>" data-guest-id="<?php echo (int)($g['guest_id'] ?? 0); ?>" data-guest-name="<?php echo h($guestLabel); ?>" data-room-no="<?php echo h($room); ?>" data-property-id="<?php echo (int)($g['property_id'] ?? 0); ?>" <?php echo $selected ? 'selected' : ''; ?>><?php echo h(($room !== '' ? 'Room '.$room.' • ' : '') . $guestLabel . ' • ' . (($g['order_no'] ?? '') ?: '#'.$g['order_id'])); ?></option>
                            <?php endforeach; ?>
                        </select>
                        <div class="form-text">Only current in-house bookings are shown.</div>
                    </div>
                    <div class="col-md-4">
                        <label class="form-label">Guest / Customer Name</label>
                        <input name="guest_name" id="guest_name" class="form-control" value="<?php echo h($form['guest_name'] ?? ''); ?>" required>
                    </div>
                    <div class="col-md-3">
                        <label class="form-label">Property</label>
                        <select name="property_id" id="property_id" class="form-select">
                            <option value="">Not set</option>
                            <?php foreach ($properties as $p): ?><option value="<?php echo (int)$p['id']; ?>" <?php echo (int)($form['property_id'] ?? 0) === (int)$p['id'] ? 'selected' : ''; ?>><?php echo h($p['name']); ?></option><?php endforeach; ?>
                        </select>
                    </div>
                    <div class="col-md-3"><label class="form-label">Date</label><input type="date" name="reservation_date" id="reservation_date" class="form-control" value="<?php echo h($form['reservation_date'] ?? date('Y-m-d')); ?>" required></div>
                    <div class="col-md-2"><label class="form-label">Time</label><input type="time" name="reservation_time" id="reservation_time" class="form-control" value="<?php echo h(substr((string)($form['reservation_time'] ?? '19:00'), 0, 5)); ?>" required></div>
                    <div class="col-md-2"><label class="form-label">Duration</label><select name="duration_minutes" id="duration_minutes" class="form-select"><?php foreach ([45,60,75,90,105,120,150,180] as $mins): ?><option value="<?php echo $mins; ?>" <?php echo (int)($form['duration_minutes'] ?? 90) === $mins ? 'selected' : ''; ?>><?php echo $mins; ?> min</option><?php endforeach; ?></select></div>
                    <div class="col-md-2"><label class="form-label">Covers</label><input type="number" name="covers" id="covers" min="1" class="form-control" value="<?php echo (int)($form['covers'] ?? 1); ?>" required></div>
                    <div class="col-md-3"><label class="form-label">Meal Period</label><select name="meal_period" class="form-select"><?php foreach (['breakfast'=>'Breakfast','lunch'=>'Lunch','dinner'=>'Dinner','other'=>'Other'] as $value => $label): ?><option value="<?php echo h($value); ?>" <?php echo ($form['meal_period'] ?? 'dinner') === $value ? 'selected' : ''; ?>><?php echo h($label); ?></option><?php endforeach; ?></select></div>
                    <div class="col-md-3"><label class="form-label">Area</label><select name="restaurant_area_id" id="restaurant_area_id" class="form-select"><option value="">Any Area</option><?php foreach ($areas as $area): ?><option value="<?php echo (int)$area['id']; ?>" <?php echo (int)($form['restaurant_area_id'] ?? 0) === (int)$area['id'] ? 'selected' : ''; ?>><?php echo h($area['area_name']); ?></option><?php endforeach; ?></select></div>
                    <div class="col-md-4">
                        <label class="form-label">Table</label>
                        <select name="table_ids[]" id="table_id" class="form-select" multiple size="6">
                            <?php foreach ($tables as $t): ?>
                                <?php $tid=(int)$t['id']; $reservedCount=(int)($availability[$tid] ?? 0); $selected=isset($editTableIdSet[$tid]); ?>
                                <option value="<?php echo $tid; ?>" data-area-id="<?php echo (int)($t['area_id'] ?? 0); ?>" data-seats="<?php echo (int)$t['seats']; ?>" data-reserved-count="<?php echo $reservedCount; ?>" <?php echo $selected ? 'selected' : ''; ?>><?php echo h(($t['area_name'] ? $t['area_name'].' • ' : '') . 'Table ' . $t['table_no'] . ' • ' . (int)$t['seats'] . ' seats' . ($reservedCount ? ' • '.$reservedCount.' booking(s) today' : '')); ?></option>
                            <?php endforeach; ?>
                        </select>
                        <div class="form-text">Hold Ctrl/Cmd to combine more than one table. Server validates overlapping bookings before saving.</div>
                        <div class="small mt-1 fw-bold" id="combinedCapacityHint"></div>
                    </div>
                    <div class="col-md-2"><label class="form-label">Status</label><select name="status" class="form-select"><?php foreach (['booked'=>'Booked','seated'=>'Seated','no_show'=>'No Show','cancelled'=>'Cancelled','completed'=>'Completed'] as $value => $label): ?><option value="<?php echo h($value); ?>" <?php echo ($form['status'] ?? 'booked') === $value ? 'selected' : ''; ?>><?php echo h($label); ?></option><?php endforeach; ?></select></div>
                    <div class="col-12"><label class="form-label">Notes / Requests</label><textarea name="notes" class="form-control" rows="3" placeholder="High chair, birthday, dietary notes, preferred table..."><?php echo h($form['notes'] ?? ''); ?></textarea></div>
                    <div class="col-12"><div class="reservation-tip"><strong><i class="bi bi-lightbulb me-1"></i>How it works:</strong> Save the booking now. When guests arrive, click <strong>Seat Guest Now</strong> to create the live restaurant order and mark the table occupied.</div></div>
                    <div class="col-12 d-flex flex-wrap gap-2 justify-content-end">
                        <a href="reservations.php" class="btn btn-outline-secondary">Cancel</a>
                        <?php if ((int)($form['id'] ?? 0) > 0): ?><button type="submit" name="action" value="seat" class="btn btn-success"><i class="bi bi-person-check me-1"></i>Seat Guest Now</button><?php endif; ?>
                        <button class="btn btn-primary"><i class="bi bi-save me-1"></i>Save Reservation</button>
                    </div>
                </form>
            </div>
        </div>
    </div>
    <div class="col-xl-4">
        <div class="card panel-card mb-3"><div class="card-header"><h5 class="mb-0">Selected Summary</h5></div><div class="card-body"><div class="summary-row"><span>Guest</span><strong id="sumGuest"><?php echo h($form['guest_name'] ?: '-'); ?></strong></div><div class="summary-row room-summary-row" style="<?php echo $isRoomGuestSource ? '' : 'display:none;'; ?>"><span>Room</span><strong id="sumRoom"><?php echo h($form['room_no'] ?: '-'); ?></strong></div><div class="summary-row"><span>Date / Time</span><strong id="sumDateTime">-</strong></div><div class="summary-row"><span>Covers</span><strong id="sumCovers"><?php echo (int)($form['covers'] ?? 1); ?></strong></div><div class="summary-row"><span>Table</span><strong id="sumTable">-</strong></div></div></div>
        <div class="card panel-card"><div class="card-header"><h5 class="mb-0">Available Table Guide</h5></div><div class="card-body"><div class="small text-muted mb-2">Use the table dropdown for allocation. If unsure, save without table and allocate from the planner.</div><div class="table-guide-list"><?php foreach ($tables as $t): ?><?php $reservedCount=(int)($availability[(int)$t['id']] ?? 0); ?><div class="table-guide-item"><div><strong>Table <?php echo h($t['table_no']); ?></strong><span><?php echo h($t['area_name'] ?: 'No area'); ?></span></div><div class="text-end"><strong><?php echo (int)$t['seats']; ?> seats</strong><span class="<?php echo $reservedCount ? 'text-warning' : 'text-success'; ?>"><?php echo $reservedCount ? $reservedCount.' today' : 'open'; ?></span></div></div><?php endforeach; ?></div></div></div>
    </div>
</div>

<style>
.compact-restaurant-hero{padding:12px 16px!important;margin-bottom:10px!important}.compact-restaurant-hero .btn{margin-left:3px;margin-bottom:3px}.panel-card{border-radius:16px;box-shadow:0 12px 30px rgba(15,23,42,.07);border:1px solid #e5e7eb}.form-label{font-size:.76rem;font-weight:800;color:#334155;margin-bottom:3px}.form-control,.form-select{min-height:36px;border-radius:10px;font-size:.88rem}.reservation-tip{border:1px solid #bfdbfe;background:linear-gradient(135deg,#eff6ff,#ffffff);border-radius:14px;padding:10px 12px;font-size:.84rem;color:#1e3a8a}.summary-row{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 0;border-bottom:1px solid #eef2f7}.summary-row:last-child{border-bottom:0}.summary-row span{font-size:.78rem;color:#64748b;text-transform:uppercase;letter-spacing:.04em;font-weight:800}.summary-row strong{text-align:right;color:#0f172a}.table-guide-list{max-height:430px;overflow:auto}.table-guide-item{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:9px 0;border-bottom:1px solid #eef2f7}.table-guide-item:last-child{border-bottom:0}.table-guide-item span{display:block;font-size:.72rem;color:#64748b}
</style>

<script>
document.addEventListener('DOMContentLoaded', function(){
    const source=document.getElementById('source'), orderSelect=document.getElementById('order_id'), guestIdInput=document.getElementById('guest_id'), guestNameInput=document.getElementById('guest_name'), roomNoHidden=document.getElementById('room_no_hidden'), propertySelect=document.getElementById('property_id'), areaSelect=document.getElementById('restaurant_area_id'), tableSelect=document.getElementById('table_id'), dateInput=document.getElementById('reservation_date'), timeInput=document.getElementById('reservation_time'), durationSelect=document.getElementById('duration_minutes'), coversInput=document.getElementById('covers'), combinedCapacityHint=document.getElementById('combinedCapacityHint');
    function selectedTableOptions(){return tableSelect ? [...tableSelect.options].filter(opt=>opt.selected && opt.value && !opt.hidden) : [];}
    function updateCombinedCapacity(){
        if(!combinedCapacityHint) return;
        const selected=selectedTableOptions();
        let seats=0; selected.forEach(opt=>{seats += parseInt(opt.dataset.seats||'0',10)||0;});
        const covers=coversInput ? (parseInt(coversInput.value||'0',10)||0) : 0;
        if(selected.length>0){
            combinedCapacityHint.textContent = selected.length>1 ? ('Combined tables: '+selected.length+' • Capacity: '+seats+' seats') : ('Selected table capacity: '+seats+' seats');
            combinedCapacityHint.className = 'small mt-1 fw-bold ' + (covers>seats ? 'text-danger' : 'text-success');
        } else {
            combinedCapacityHint.textContent='No table allocated yet.';
            combinedCapacityHint.className='small mt-1 fw-bold text-muted';
        }
    }
    function syncSource(){
        const isRoomGuest=source&&source.value==='room_guest';
        document.querySelectorAll('.room-guest-field').forEach(el=>el.style.display=isRoomGuest?'':'none');
        document.querySelectorAll('.room-summary-row').forEach(el=>el.style.display=isRoomGuest?'':'none');
        if(!isRoomGuest){
            if(orderSelect) orderSelect.value='';
            if(guestIdInput) guestIdInput.value='';
            if(roomNoHidden) roomNoHidden.value='';
            if(guestNameInput&&guestNameInput.value.trim()==='') guestNameInput.value=source.value==='walkin'?'Direct Sale':'External Guest';
        }
        updateSummary();
    }
    function syncGuest(){
        const opt=orderSelect?orderSelect.options[orderSelect.selectedIndex]:null;
        if(opt&&opt.value){
            if(guestNameInput)guestNameInput.value=opt.dataset.guestName||'';
            if(guestIdInput)guestIdInput.value=opt.dataset.guestId||'';
            if(roomNoHidden)roomNoHidden.value=opt.dataset.roomNo||'';
            if(propertySelect&&opt.dataset.propertyId)propertySelect.value=opt.dataset.propertyId;
        }
        updateSummary();
    }
    function filterTables(){
        const areaId=areaSelect?String(areaSelect.value||''):'';
        if(!tableSelect) return;
        [...tableSelect.options].forEach(opt=>{
            if(!opt.value){opt.hidden=false;return;}
            const optArea=String(opt.dataset.areaId||'');
            opt.hidden=!!(areaId&&optArea!==areaId);
            if(opt.hidden && opt.selected) opt.selected=false;
        });
        updateCombinedCapacity();
        updateSummary();
    }
    function updateSummary(){
        const sumGuest=document.getElementById('sumGuest'),sumRoom=document.getElementById('sumRoom'),sumDateTime=document.getElementById('sumDateTime'),sumCovers=document.getElementById('sumCovers'),sumTable=document.getElementById('sumTable');
        const isRoomGuest=source&&source.value==='room_guest';
        const room=isRoomGuest && roomNoHidden ? roomNoHidden.value : '';
        if(sumGuest)sumGuest.textContent=guestNameInput&&guestNameInput.value?guestNameInput.value:'-';
        if(sumRoom)sumRoom.textContent=room||'-';
        if(sumDateTime){const date=dateInput?dateInput.value:'',time=timeInput?timeInput.value:'',dur=durationSelect?durationSelect.value:'';sumDateTime.textContent=(date||'-')+' '+(time||'')+(dur?' • '+dur+' min':'');}
        if(sumCovers)sumCovers.textContent=coversInput?(coversInput.value||'1'):'1';
        if(sumTable){
            const selected=selectedTableOptions();
            sumTable.textContent=selected.length ? selected.map(opt=>opt.textContent.trim().replace(/\s+/g,' ')).join(' + ') : 'Allocate later';
        }
        updateCombinedCapacity();
    }
    if(source)source.addEventListener('change',syncSource);
    if(orderSelect)orderSelect.addEventListener('change',syncGuest);
    if(areaSelect)areaSelect.addEventListener('change',filterTables);
    if(tableSelect)tableSelect.addEventListener('change',updateSummary);
    if(coversInput)coversInput.addEventListener('input',updateSummary);
    [guestNameInput,dateInput,timeInput,durationSelect].forEach(el=>{if(el)el.addEventListener('input',updateSummary);if(el)el.addEventListener('change',updateSummary);});
    syncSource();syncGuest();filterTables();updateSummary();
});
</script>

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