'Coach ID is required']); exit; } $coach_id = $_GET['coach_id']; $start_date_str = isset($_GET['start']) ? $_GET['start'] : 'first day of this month'; $end_date_str = isset($_GET['end']) ? $_GET['end'] : 'last day of this month'; // Fetch coach data $coach_stmt = db()->prepare("SELECT buffer_time, timezone FROM coaches WHERE id = ?"); $coach_stmt->execute([$coach_id]); $coach = $coach_stmt->fetch(); $buffer_time = $coach ? (int)$coach['buffer_time'] : 0; $coach_timezone = new DateTimeZone($coach ? $coach['timezone'] : 'UTC'); // Fetch client timezone $client_timezone_str = 'UTC'; // Default if (isset($_SESSION['user_id'])) { $client_stmt = db()->prepare("SELECT timezone FROM clients WHERE id = ?"); $client_stmt->execute([$_SESSION['user_id']]); $client = $client_stmt->fetch(); if ($client && $client['timezone']) { $client_timezone_str = $client['timezone']; } } $client_timezone = new DateTimeZone($client_timezone_str); $start_date = new DateTime($start_date_str, $client_timezone); $end_date = new DateTime($end_date_str, $client_timezone); $response = [ 'availability' => [], 'bookings' => [] ]; // Helper function to convert time function convert_time($time_str, $from_tz, $to_tz) { $dt = new DateTime($time_str, $from_tz); $dt->setTimezone($to_tz); return $dt->format('Y-m-d H:i:s'); } // Fetch one-off availability $stmt_availability = db()->prepare("SELECT start_time, end_time FROM coach_availability WHERE coach_id = ? AND start_time BETWEEN ? AND ?"); $stmt_availability->execute([$coach_id, $start_date->format('Y-m-d H:i:s'), $end_date->format('Y-m-d H:i:s')]); $one_off_availability = $stmt_availability->fetchAll(PDO::FETCH_ASSOC); foreach ($one_off_availability as $slot) { $response['availability'][] = [ 'start_time' => convert_time($slot['start_time'], $coach_timezone, $client_timezone), 'end_time' => convert_time($slot['end_time'], $coach_timezone, $client_timezone) ]; } // Fetch recurring availability and generate slots $stmt_recurring = db()->prepare("SELECT day_of_week, start_time, end_time FROM coach_recurring_availability WHERE coach_id = ?"); $stmt_recurring->execute([$coach_id]); $recurring_availability = $stmt_recurring->fetchAll(PDO::FETCH_ASSOC); $interval = new DateInterval('P1D'); $period = new DatePeriod($start_date, $interval, $end_date->modify('+1 day')); foreach ($period as $date) { $day_of_week = $date->format('w'); foreach ($recurring_availability as $rule) { if ((int)$rule['day_of_week'] === (int)$day_of_week) { $start_time_str = $date->format('Y-m-d') . ' ' . $rule['start_time']; $end_time_str = $date->format('Y-m-d') . ' ' . $rule['end_time']; $start_dt = new DateTime($start_time_str, $coach_timezone); if ($start_dt >= new DateTime('now', $coach_timezone)) { $response['availability'][] = [ 'start_time' => convert_time($start_time_str, $coach_timezone, $client_timezone), 'end_time' => convert_time($end_time_str, $coach_timezone, $client_timezone) ]; } } } } // Fetch confirmed and pending bookings $stmt_bookings = db()->prepare("SELECT booking_time FROM bookings WHERE coach_id = ? AND (status = 'confirmed' OR status = 'pending') AND booking_time BETWEEN ? AND ?"); $stmt_bookings->execute([$coach_id, $start_date->format('Y-m-d H:i:s'), $end_date->format('Y-m-d H:i:s')]); $bookings = $stmt_bookings->fetchAll(PDO::FETCH_ASSOC); // Assume each booking is for one hour and add buffer foreach ($bookings as $booking) { $start_booking_time = new DateTime($booking['booking_time'], $coach_timezone); $end_booking_time = clone $start_booking_time; $end_booking_time->add(new DateInterval('PT1H')); // Assuming 1-hour bookings $end_booking_time->add(new DateInterval('PT' . $buffer_time . 'M')); $response['bookings'][] = [ 'start_time' => $start_booking_time->setTimezone($client_timezone)->format('Y-m-d H:i:s'), 'end_time' => $end_booking_time->setTimezone($client_timezone)->format('Y-m-d H:i:s') ]; } echo json_encode($response);