<?php
/**
 * RUHONDO BEACH RESORT HMS + POS System
 * Reservations API
 * Developer: JOACHIM'S INNOTECH
 */

// Verify authentication
$user_id = verify_api_request();
if (!$user_id) {
    json_response(['error' => 'Authentication required'], 401);
}

// Get current user
$current_user = db_fetch_one("SELECT * FROM users WHERE user_id = ?", [$user_id]);

// Handle different methods
switch ($method) {
    case 'GET':
        if ($id) {
            get_single_reservation($id);
        } else {
            get_reservations_list();
        }
        break;
        
    case 'POST':
        create_reservation();
        break;
        
    case 'PUT':
        if (!$id) {
            json_response(['error' => 'Reservation ID required'], 400);
        }
        update_reservation($id);
        break;
        
    case 'DELETE':
        if (!$id) {
            json_response(['error' => 'Reservation ID required'], 400);
        }
        cancel_reservation($id);
        break;
        
    default:
        json_response(['error' => 'Method not allowed'], 405);
}

/**
 * Get list of reservations
 */
function get_reservations_list() {
    global $user_id;
    
    // Get query parameters
    $page = max(1, (int)($_GET['page'] ?? 1));
    $limit = min(100, max(1, (int)($_GET['limit'] ?? 20)));
    $status = $_GET['status'] ?? '';
    $date_from = $_GET['date_from'] ?? '';
    $date_to = $_GET['date_to'] ?? '';
    $guest_id = isset($_GET['guest_id']) ? (int)$_GET['guest_id'] : null;
    
    // Build where clause
    $where = "1=1";
    $params = [];
    
    if (!empty($status)) {
        $where .= " AND booking_status = ?";
        $params[] = $status;
    }
    
    if (!empty($date_from)) {
        $where .= " AND check_in_date >= ?";
        $params[] = $date_from;
    }
    
    if (!empty($date_to)) {
        $where .= " AND check_out_date <= ?";
        $params[] = $date_to;
    }
    
    if ($guest_id) {
        $where .= " AND guest_id = ?";
        $params[] = $guest_id;
    }
    
    // Get total count
    $count_sql = "SELECT COUNT(*) FROM reservations WHERE $where";
    $total = db_fetch_value($count_sql, $params);
    
    // Get paginated results
    $offset = ($page - 1) * $limit;
    $sql = "
        SELECT 
            r.*,
            g.first_name, g.last_name, g.email, g.phone,
            rt.type_name,
            rm.room_number
        FROM reservations r
        JOIN guests g ON r.guest_id = g.guest_id
        JOIN room_types rt ON r.room_type_id = rt.room_type_id
        LEFT JOIN rooms rm ON r.room_id = rm.room_id
        WHERE $where
        ORDER BY r.check_in_date DESC
        LIMIT $limit OFFSET $offset
    ";
    
    $reservations = db_fetch_all($sql, $params);
    
    // Format response
    $items = [];
    foreach ($reservations as $res) {
        $items[] = [
            'reservation_id' => $res['reservation_id'],
            'booking_code' => $res['booking_code'],
            'guest' => [
                'id' => $res['guest_id'],
                'name' => $res['first_name'] . ' ' . $res['last_name'],
                'email' => $res['email'],
                'phone' => $res['phone']
            ],
            'room_type' => $res['type_name'],
            'room_number' => $res['room_number'],
            'check_in' => $res['check_in_date'],
            'check_out' => $res['check_out_date'],
            'nights' => $res['nights'],
            'adults' => $res['adults'],
            'children' => $res['children'],
            'total_amount' => (float)$res['total_amount'],
            'paid_amount' => (float)$res['paid_amount'],
            'balance' => (float)($res['total_amount'] - $res['paid_amount']),
            'status' => $res['booking_status'],
            'source' => $res['booking_source'],
            'created_at' => $res['created_at']
        ];
    }
    
    json_response([
        'success' => true,
        'data' => $items,
        'pagination' => [
            'page' => $page,
            'limit' => $limit,
            'total' => (int)$total,
            'pages' => ceil($total / $limit)
        ]
    ]);
}

/**
 * Get single reservation
 */
function get_single_reservation($id) {
    $reservation = db_fetch_one("
        SELECT 
            r.*,
            g.guest_id, g.first_name, g.last_name, g.email, g.phone,
            g.address, g.city, g.country,
            rt.type_name, rt.type_code,
            rm.room_number, rm.floor
        FROM reservations r
        JOIN guests g ON r.guest_id = g.guest_id
        JOIN room_types rt ON r.room_type_id = rt.room_type_id
        LEFT JOIN rooms rm ON r.room_id = rm.room_id
        WHERE r.reservation_id = ?
    ", [$id]);
    
    if (!$reservation) {
        json_response(['error' => 'Reservation not found'], 404);
    }
    
    // Get folio charges
    $charges = db_fetch_all("
        SELECT * FROM folio_charges 
        WHERE reservation_id = ? AND is_voided = 0
        ORDER BY posted_at
    ", [$id]);
    
    json_response([
        'success' => true,
        'data' => [
            'reservation' => $reservation,
            'folio' => $charges
        ]
    ]);
}

/**
 * Create new reservation
 */
function create_reservation() {
    global $current_user;
    
    // Get POST data
    $input = json_decode(file_get_contents('php://input'), true);
    
    if (!$input) {
        json_response(['error' => 'Invalid request data'], 400);
    }
    
    // Validate required fields
    $required = ['guest_id', 'room_type_id', 'check_in_date', 'check_out_date', 'adults'];
    foreach ($required as $field) {
        if (empty($input[$field])) {
            json_response(['error' => "Field '$field' is required"], 400);
        }
    }
    
    // Validate dates
    if ($input['check_in_date'] >= $input['check_out_date']) {
        json_response(['error' => 'Check-out date must be after check-in date'], 400);
    }
    
    // Check guest exists
    $guest = db_fetch_one("SELECT * FROM guests WHERE guest_id = ?", [$input['guest_id']]);
    if (!$guest) {
        json_response(['error' => 'Guest not found'], 404);
    }
    
    // Check room type exists
    $room_type = db_fetch_one("SELECT * FROM room_types WHERE room_type_id = ?", [$input['room_type_id']]);
    if (!$room_type) {
        json_response(['error' => 'Room type not found'], 404);
    }
    
    // Check availability if room specified
    if (!empty($input['room_id'])) {
        $available = check_room_availability(
            $input['room_id'],
            $input['check_in_date'],
            $input['check_out_date']
        );
        
        if (!$available) {
            json_response(['error' => 'Selected room is not available'], 400);
        }
    }
    
    try {
        begin_transaction();
        
        // Generate booking code
        $booking_code = generate_booking_code();
        
        // Calculate nights
        $nights = calculate_nights($input['check_in_date'], $input['check_out_date']);
        
        // Calculate total amount (simplified - in production use rate calculation)
        $total_amount = $room_type['base_price'] * $nights;
        
        // Create reservation
        $reservation_id = db_insert('reservations', [
            'booking_code' => $booking_code,
            'guest_id' => $input['guest_id'],
            'room_type_id' => $input['room_type_id'],
            'room_id' => $input['room_id'] ?? null,
            'rate_plan_id' => $input['rate_plan_id'] ?? null,
            'adults' => $input['adults'],
            'children' => $input['children'] ?? 0,
            'check_in_date' => $input['check_in_date'],
            'check_out_date' => $input['check_out_date'],
            'nights' => $nights,
            'booking_source' => $input['source'] ?? 'api',
            'booking_status' => $input['status'] ?? 'confirmed',
            'payment_status' => 'unpaid',
            'total_amount' => $total_amount,
            'paid_amount' => 0,
            'special_requests' => $input['special_requests'] ?? null,
            'created_by' => $current_user['user_id']
        ]);
        
        // Create guest activity
        db_insert('guest_activity', [
            'guest_id' => $input['guest_id'],
            'activity_type' => 'api_booking',
            'description' => "Reservation created via API: $booking_code",
            'reference_id' => $reservation_id,
            'reference_type' => 'reservation',
            'created_by' => $current_user['user_id']
        ]);
        
        commit_transaction();
        
        // Get created reservation
        $reservation = db_fetch_one("
            SELECT * FROM reservations WHERE reservation_id = ?
        ", [$reservation_id]);
        
        json_response([
            'success' => true,
            'message' => 'Reservation created successfully',
            'data' => $reservation
        ], 201);
        
    } catch (Exception $e) {
        rollback_transaction();
        json_response(['error' => 'Failed to create reservation: ' . $e->getMessage()], 500);
    }
}

/**
 * Update reservation
 */
function update_reservation($id) {
    global $current_user;
    
    // Check if reservation exists
    $reservation = db_fetch_one("SELECT * FROM reservations WHERE reservation_id = ?", [$id]);
    if (!$reservation) {
        json_response(['error' => 'Reservation not found'], 404);
    }
    
    // Check if reservation can be modified
    if (in_array($reservation['booking_status'], ['checked_out', 'cancelled'])) {
        json_response(['error' => 'Reservation cannot be modified'], 400);
    }
    
    // Get PUT data
    $input = json_decode(file_get_contents('php://input'), true);
    
    if (!$input) {
        json_response(['error' => 'Invalid request data'], 400);
    }
    
    try {
        begin_transaction();
        
        $update_data = [];
        
        // Update fields if provided
        $allowed_fields = ['adults', 'children', 'special_requests', 'room_id'];
        foreach ($allowed_fields as $field) {
            if (isset($input[$field])) {
                $update_data[$field] = $input[$field];
            }
        }
        
        // Handle date changes
        if (isset($input['check_in_date']) || isset($input['check_out_date'])) {
            $check_in = $input['check_in_date'] ?? $reservation['check_in_date'];
            $check_out = $input['check_out_date'] ?? $reservation['check_out_date'];
            
            if ($check_in >= $check_out) {
                json_response(['error' => 'Check-out date must be after check-in date'], 400);
            }
            
            $update_data['check_in_date'] = $check_in;
            $update_data['check_out_date'] = $check_out;
            $update_data['nights'] = calculate_nights($check_in, $check_out);
            
            // Recalculate total if needed
            // In production, use rate calculation
        }
        
        if (!empty($update_data)) {
            db_update('reservations', $update_data, 'reservation_id = ?', [$id]);
        }
        
        commit_transaction();
        
        // Get updated reservation
        $updated = db_fetch_one("SELECT * FROM reservations WHERE reservation_id = ?", [$id]);
        
        json_response([
            'success' => true,
            'message' => 'Reservation updated successfully',
            'data' => $updated
        ]);
        
    } catch (Exception $e) {
        rollback_transaction();
        json_response(['error' => 'Failed to update reservation: ' . $e->getMessage()], 500);
    }
}

/**
 * Cancel reservation
 */
function cancel_reservation($id) {
    global $current_user;
    
    // Check if reservation exists
    $reservation = db_fetch_one("SELECT * FROM reservations WHERE reservation_id = ?", [$id]);
    if (!$reservation) {
        json_response(['error' => 'Reservation not found'], 404);
    }
    
    // Check if can be cancelled
    if (in_array($reservation['booking_status'], ['checked_out', 'cancelled', 'no_show'])) {
        json_response(['error' => 'Reservation cannot be cancelled'], 400);
    }
    
    // Get cancellation data
    $input = json_decode(file_get_contents('php://input'), true);
    $reason = $input['reason'] ?? 'Cancelled via API';
    
    try {
        begin_transaction();
        
        // Update reservation
        db_update('reservations', [
            'booking_status' => 'cancelled',
            'cancel_reason' => $reason,
            'cancelled_at' => date(DATETIME_FORMAT),
            'cancelled_by' => $current_user['user_id']
        ], 'reservation_id = ?', [$id]);
        
        // Free up room if assigned
        if ($reservation['room_id']) {
            db_update('rooms', ['status' => 'available'], 'room_id = ?', [$reservation['room_id']]);
        }
        
        // Create guest activity
        db_insert('guest_activity', [
            'guest_id' => $reservation['guest_id'],
            'activity_type' => 'cancellation',
            'description' => "Reservation cancelled via API: $reason",
            'reference_id' => $id,
            'reference_type' => 'reservation',
            'created_by' => $current_user['user_id']
        ]);
        
        commit_transaction();
        
        json_response([
            'success' => true,
            'message' => 'Reservation cancelled successfully'
        ]);
        
    } catch (Exception $e) {
        rollback_transaction();
        json_response(['error' => 'Failed to cancel reservation: ' . $e->getMessage()], 500);
    }
}

/**
 * Check room availability helper
 */
function check_room_availability($room_id, $check_in, $check_out, $exclude_id = null) {
    $sql = "
        SELECT COUNT(*) FROM reservations 
        WHERE room_id = ?
        AND booking_status IN ('confirmed', 'checked_in')
        AND check_in_date < ? AND check_out_date > ?
    ";
    $params = [$room_id, $check_out, $check_in];
    
    if ($exclude_id) {
        $sql .= " AND reservation_id != ?";
        $params[] = $exclude_id;
    }
    
    $count = db_fetch_value($sql, $params);
    return $count == 0;
}