<?php
/**
 * Manager Reservations/Bookings API
 * Handles table reservations and bookings management
 */

session_start();
require 'config.php';

header('Content-Type: application/json');

// Release any expired bookings before processing requests
releaseExpiredBookings($conn);

// Check manager authentication
// Accept manager_id from session or from GET parameter (for client-side authentication)
$manager_id = null;

if (isset($_SESSION['manager_id'])) {
    $manager_id = $_SESSION['manager_id'];
} elseif (isset($_GET['manager_id'])) {
    $manager_id = intval($_GET['manager_id']);
    // Validate the manager exists
    $validateRes = $conn->query("SELECT id FROM managers WHERE id = " . $manager_id . " LIMIT 1");
    if (!$validateRes || $validateRes->num_rows === 0) {
        http_response_code(401);
        sendResponse(false, 'Unauthorized access', null);
        exit;
    }
} else {
    http_response_code(401);
    sendResponse(false, 'Unauthorized access', null);
    exit;
}
$action = isset($_GET['action']) ? $_GET['action'] : '';

switch ($action) {
    case 'list':
        listBookings();
        break;
    case 'get':
        getBooking();
        break;
    case 'today':
        getTodayBookings();
        break;
    case 'upcoming':
        getUpcomingBookings();
        break;
    case 'confirm':
        confirmBooking();
        break;
    case 'checkin':
        checkinBooking();
        break;
    case 'cancel':
        cancelBooking();
        break;
    case 'no_show':
        markNoShow();
        break;
    case 'get_available_tables':
        getAvailableTablesForBooking();
        break;
    case 'allocate_table_to_booking':
        allocateTableToBooking();
        break;
    case 'get_booking_stats':
        getBookingStats();
        break;
    default:
        sendResponse(false, 'Invalid action', null);
}

// List all bookings with filters
function listBookings() {
    global $conn;
    
    $status = isset($_GET['status']) ? $_GET['status'] : '';
    $start_date = isset($_GET['start_date']) ? $_GET['start_date'] : date('Y-m-d');
    $end_date = isset($_GET['end_date']) ? $_GET['end_date'] : date('Y-m-d');
    $page = isset($_GET['page']) ? intval($_GET['page']) : 1;
    $limit = isset($_GET['limit']) ? intval($_GET['limit']) : 20;
    $offset = ($page - 1) * $limit;
    
    $sql = "SELECT b.*, 
            (SELECT COUNT(*) FROM table_bookings WHERE booking_id = b.id) as assigned_tables
            FROM bookings b 
            WHERE booking_date BETWEEN '" . $conn->real_escape_string($start_date) . "' 
                   AND '" . $conn->real_escape_string($end_date) . "'";
    
    if ($status) {
        $sql .= " AND b.status = '" . $conn->real_escape_string($status) . "'";
    }
    
    $sql .= " ORDER BY booking_date DESC, slot_time DESC LIMIT " . $offset . ", " . $limit;
    
    $result = $conn->query($sql);
    
    $bookings = [];
    while ($row = $result->fetch_assoc()) {
        $bookings[] = $row;
    }
    
    // Get total count
    $count_sql = "SELECT COUNT(id) as total FROM bookings 
                  WHERE booking_date BETWEEN '" . $conn->real_escape_string($start_date) . "' 
                  AND '" . $conn->real_escape_string($end_date) . "'";
    if ($status) {
        $count_sql .= " AND status = '" . $conn->real_escape_string($status) . "'";
    }
    
    $count_result = $conn->query($count_sql);
    $total = $count_result->fetch_assoc()['total'];
    
    sendResponse(true, 'Bookings retrieved', [
        'bookings' => $bookings,
        'total' => $total,
        'page' => $page,
        'limit' => $limit
    ]);
}

// Get booking details
function getBooking() {
    global $conn;
    
    if (!isset($_GET['booking_id'])) {
        sendResponse(false, 'Booking ID is required', null);
    }
    
    $booking_id = intval($_GET['booking_id']);
    
    $sql = "SELECT * FROM bookings WHERE id = " . $booking_id;
    $result = $conn->query($sql);
    
    if ($result->num_rows === 0) {
        sendResponse(false, 'Booking not found', null);
    }
    
    $booking = $result->fetch_assoc();
    
    // Get assigned tables from restaurant table allocations
    // Filter out tables with status = 'merged' (secondary merged tables)
    $tables_sql = "SELECT rt.*, COALESCE(tb.assigned_table_name, rt.table_number) as display_name
                   FROM restaurant_tables rt
                   INNER JOIN table_bookings tb ON rt.id = tb.table_id
                   WHERE tb.booking_id = " . $booking_id . " AND rt.status != 'merged'";
    $tables_result = $conn->query($tables_sql);
    $booking['assigned_tables'] = [];
    while ($row = $tables_result->fetch_assoc()) {
        $booking['assigned_tables'][] = $row;
    }

    // Also include online table allocations
    $online_tables_sql = "SELECT ot.id, ot.table_number,
                                 ot.base_capacity as capacity,
                                 ot.floor_level as floor,
                                 ot.section,
                                 ot.status,
                                 ot.table_number as display_name
                          FROM online_tables ot
                          INNER JOIN online_table_bookings otb ON ot.id = otb.online_table_id
                          WHERE otb.booking_id = " . $booking_id . "
                            AND otb.allocation_status = 'allocated'";
    $online_tables_result = $conn->query($online_tables_sql);
    while ($online_tables_result && $row = $online_tables_result->fetch_assoc()) {
        $booking['assigned_tables'][] = $row;
    }
    
    sendResponse(true, 'Booking retrieved', $booking);
}

// Get today's bookings
function getTodayBookings() {
    global $conn;
    
    // Get date from parameter or use today
    $date = isset($_GET['date']) ? $_GET['date'] : date('Y-m-d');
    
    // Validate date format
    if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $date)) {
        $date = date('Y-m-d');
    }
    
    // Include both restaurant table allocations and online table allocations
    $sql = "SELECT b.*,
            TRIM(BOTH ', ' FROM CONCAT_WS(', ',
                (SELECT GROUP_CONCAT(DISTINCT COALESCE(tb.assigned_table_name, rt.table_number) SEPARATOR ', ')
                 FROM restaurant_tables rt
                 INNER JOIN table_bookings tb ON rt.id = tb.table_id
                 WHERE tb.booking_id = b.id AND rt.status != 'merged'),
                (SELECT GROUP_CONCAT(DISTINCT ot.table_number SEPARATOR ', ')
                 FROM online_table_bookings otb
                 INNER JOIN online_tables ot ON otb.online_table_id = ot.id
                 WHERE otb.booking_id = b.id AND otb.allocation_status = 'allocated')
            )) as table_numbers
            FROM bookings b
            WHERE booking_date = '" . $conn->real_escape_string($date) . "'
            ORDER BY slot_time ASC";
    
    $result = $conn->query($sql);
    
    $bookings = [];
    while ($row = $result->fetch_assoc()) {
        $bookings[] = $row;
    }
    
    sendResponse(true, 'Bookings for ' . $date . ' retrieved', $bookings);
}

// Get upcoming bookings
function getUpcomingBookings() {
    global $conn;
    
    $days = isset($_GET['days']) ? intval($_GET['days']) : 7;
    
    // Include both restaurant table allocations and online table allocations
    $sql = "SELECT b.*,
            TRIM(BOTH ', ' FROM CONCAT_WS(', ',
                (SELECT GROUP_CONCAT(DISTINCT COALESCE(tb.assigned_table_name, rt.table_number) SEPARATOR ', ')
                 FROM restaurant_tables rt
                 INNER JOIN table_bookings tb ON rt.id = tb.table_id
                 WHERE tb.booking_id = b.id AND rt.status != 'merged'),
                (SELECT GROUP_CONCAT(DISTINCT ot.table_number SEPARATOR ', ')
                 FROM online_table_bookings otb
                 INNER JOIN online_tables ot ON otb.online_table_id = ot.id
                 WHERE otb.booking_id = b.id AND otb.allocation_status = 'allocated')
            )) as table_numbers
            FROM bookings b
            WHERE booking_date BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL " . $days . " DAY)
            AND b.status IN ('pending', 'confirmed')
            ORDER BY booking_date ASC, slot_time ASC";
    
    $result = $conn->query($sql);
    
    $bookings = [];
    while ($row = $result->fetch_assoc()) {
        $bookings[] = $row;
    }
    
    sendResponse(true, 'Upcoming bookings retrieved', $bookings);
}

// Confirm a booking
function confirmBooking() {
    global $conn, $manager_id;
    
    $data = json_decode(file_get_contents("php://input"), true);
    
    if (!isset($data['booking_id'])) {
        sendResponse(false, 'Booking ID is required', null);
    }
    
    $booking_id = intval($data['booking_id']);
    $notes = isset($data['notes']) ? $data['notes'] : '';
    
    $sql = "UPDATE bookings SET status = 'confirmed' WHERE id = " . $booking_id;
    
    if ($conn->query($sql)) {
        sendResponse(true, 'Booking confirmed', null);
    } else {
        sendResponse(false, 'Error confirming booking', null);
    }
}

// Check in a booking (customer arrives)
function checkinBooking() {
    global $conn, $manager_id;
    
    $data = json_decode(file_get_contents("php://input"), true);
    
    if (!isset($data['booking_id'])) {
        sendResponse(false, 'Booking ID is required', null);
    }
    
    $booking_id = intval($data['booking_id']);
    
    $sql = "UPDATE bookings SET status = 'checked_in' WHERE id = " . $booking_id;
    
    if ($conn->query($sql)) {
        sendResponse(true, 'Booking checked in', null);
    } else {
        sendResponse(false, 'Error checking in booking', null);
    }
}

// Cancel a booking
function cancelBooking() {
    global $conn;
    
    $data = json_decode(file_get_contents("php://input"), true);
    
    if (!isset($data['booking_id'])) {
        sendResponse(false, 'Booking ID is required', null);
    }
    
    $booking_id = intval($data['booking_id']);
    $reason = isset($data['reason']) ? $conn->real_escape_string($data['reason']) : '';
    
    $sql = "UPDATE bookings SET status = 'cancelled' WHERE id = " . $booking_id;
    
    if ($conn->query($sql)) {
        // Release assigned tables
        $release_sql = "UPDATE restaurant_tables rt
                        SET status = 'available'
                        WHERE id IN (
                            SELECT table_id FROM table_bookings 
                            WHERE booking_id = " . $booking_id . "
                        )";
        $conn->query($release_sql);
        
        sendResponse(true, 'Booking cancelled', null);
    } else {
        sendResponse(false, 'Error cancelling booking', null);
    }
}

// Mark as no-show
function markNoShow() {
    global $conn;
    
    $data = json_decode(file_get_contents("php://input"), true);
    
    if (!isset($data['booking_id'])) {
        sendResponse(false, 'Booking ID is required', null);
    }
    
    $booking_id = intval($data['booking_id']);
    
    $sql = "UPDATE bookings SET status = 'no_show' WHERE id = " . $booking_id;
    
    if ($conn->query($sql)) {
        // Release assigned tables
        $release_sql = "UPDATE restaurant_tables rt
                        SET status = 'available'
                        WHERE id IN (
                            SELECT table_id FROM table_bookings 
                            WHERE booking_id = " . $booking_id . "
                        )";
        $conn->query($release_sql);
        
        sendResponse(true, 'Marked as no-show', null);
    } else {
        sendResponse(false, 'Error marking no-show', null);
    }
}

// Get available tables for booking
function getAvailableTablesForBooking() {
    global $conn;
    
    if (!isset($_GET['booking_id'])) {
        sendResponse(false, 'Booking ID is required', null);
    }
    
    $booking_id = intval($_GET['booking_id']);
    
    // Get booking details
    $booking_sql = "SELECT guests FROM bookings WHERE id = " . $booking_id;
    $booking_result = $conn->query($booking_sql);
    
    if ($booking_result->num_rows === 0) {
        sendResponse(false, 'Booking not found', null);
    }
    
    $booking = $booking_result->fetch_assoc();
    $guests = $booking['guests'];
    
    // Get available tables that can accommodate the guests
    $tables_sql = "SELECT rt.* FROM restaurant_tables rt
                   WHERE rt.status = 'available'
                   AND rt.base_capacity >= " . $guests . "
                   AND rt.id NOT IN (
                       SELECT table_id FROM table_bookings 
                       WHERE booking_id = " . $booking_id . "
                   )
                   ORDER BY rt.base_capacity ASC, rt.floor_level, rt.section";
    
    $tables_result = $conn->query($tables_sql);
    
    $tables = [];
    while ($row = $tables_result->fetch_assoc()) {
        $tables[] = $row;
    }
    
    sendResponse(true, 'Available tables retrieved', $tables);
}

// Allocate table to booking
function allocateTableToBooking() {
    global $conn, $manager_id;
    
    $data = json_decode(file_get_contents("php://input"), true);
    
    if (!isset($data['booking_id']) || !isset($data['table_id'])) {
        sendResponse(false, 'Booking ID and table ID are required', null);
    }
    
    $booking_id = intval($data['booking_id']);
    $table_id = intval($data['table_id']);
    
    // Get booking date
    $booking_sql = "SELECT booking_date FROM bookings WHERE id = " . $booking_id;
    $booking_result = $conn->query($booking_sql);
    if ($booking_result->num_rows === 0) {
        sendResponse(false, 'Booking not found', null);
    }
    $booking = $booking_result->fetch_assoc();
    $booking_date = $booking['booking_date'];
    
    // Check if already allocated
    $check_sql = "SELECT id FROM table_bookings 
                  WHERE booking_id = " . $booking_id . " AND table_id = " . $table_id;
    $check_result = $conn->query($check_sql);
    
    if ($check_result->num_rows > 0) {
        sendResponse(false, 'Table already allocated to this booking', null);
    }
    
    // Check if table is already allocated for this specific date
    $date_conflict_sql = "SELECT COUNT(*) as conflict_count FROM table_bookings tb
                         INNER JOIN bookings b ON tb.booking_id = b.id
                         WHERE tb.table_id = " . $table_id . "
                         AND b.booking_date = '" . $conn->real_escape_string($booking_date) . "'
                         AND b.id != " . $booking_id . "
                         AND b.status IN ('pending', 'confirmed', 'checked_in')";
    $conflict_result = $conn->query($date_conflict_sql);
    $conflict_row = $conflict_result->fetch_assoc();
    
    if ($conflict_row['conflict_count'] > 0) {
        sendResponse(false, 'Table is already allocated for ' . date('F j, Y', strtotime($booking_date)), null);
    }
    
    // Allocate table
    $insert_sql = "INSERT INTO table_bookings (booking_id, table_id) 
                   VALUES (" . $booking_id . ", " . $table_id . ")";
    
    if ($conn->query($insert_sql)) {
        // Check if table has any active bookings and update status accordingly
        $check_active_sql = "SELECT COUNT(*) as active_count FROM table_bookings tb
                            INNER JOIN bookings b ON tb.booking_id = b.id
                            WHERE tb.table_id = " . $table_id . "
                            AND b.status IN ('pending', 'confirmed', 'checked_in')";
        $active_result = $conn->query($check_active_sql);
        $active_row = $active_result->fetch_assoc();
        
        // Update table status to booked only if it has active bookings
        if ($active_row['active_count'] > 0) {
            $update_sql = "UPDATE restaurant_tables SET status = 'booked' WHERE id = " . $table_id;
            $conn->query($update_sql);
        }
        
        sendResponse(true, 'Table allocated to booking', null);
    } else {
        sendResponse(false, 'Error allocating table', null);
    }
}

// Get booking statistics
function getBookingStats() {
    global $conn;
    
    $date = isset($_GET['date']) ? $_GET['date'] : date('Y-m-d');
    
    $stats = [];
    
    // Total bookings for the day
    $total_sql = "SELECT COUNT(id) as total FROM bookings WHERE booking_date = '" . 
                 $conn->real_escape_string($date) . "'";
    $stats['total_bookings'] = $conn->query($total_sql)->fetch_assoc()['total'] ?? 0;
    
    // By status
    $status_sql = "SELECT status, COUNT(id) as count FROM bookings 
                   WHERE booking_date = '" . $conn->real_escape_string($date) . "'
                   GROUP BY status";
    $status_result = $conn->query($status_sql);
    $stats['by_status'] = [];
    while ($row = $status_result->fetch_assoc()) {
        $stats['by_status'][] = $row;
    }
    
    // Total guests
    $guests_sql = "SELECT SUM(guests) as total_guests FROM bookings 
                   WHERE booking_date = '" . $conn->real_escape_string($date) . "'";
    $stats['total_guests'] = $conn->query($guests_sql)->fetch_assoc()['total_guests'] ?? 0;
    
    // Peak time
    $peak_sql = "SELECT slot_time, COUNT(id) as count FROM bookings 
                 WHERE booking_date = '" . $conn->real_escape_string($date) . "'
                 GROUP BY slot_time
                 ORDER BY count DESC LIMIT 1";
    $peak_result = $conn->query($peak_sql);
    $stats['peak_time'] = $peak_result->num_rows > 0 ? 
                          $peak_result->fetch_assoc() : null;
    
    sendResponse(true, 'Booking statistics retrieved', $stats);
}
?>
