false, 'message' => 'Method not allowed'], 405); } // Require authentication for stats requireAuth(); $action = $_GET['action'] ?? 'all'; $forceRefresh = !empty($_GET['refresh']); switch ($action) { case 'all': getAllStats(); break; case 'bookings': getBookingStats(); break; case 'messages': getMessageStats(); break; case 'news': getNewsStats(); break; default: getAllStats(); } function getAllStats() { $cacheKey = 'stats_all_v1'; if (!$GLOBALS['forceRefresh']) { $cached = getStatsCache($cacheKey, 30); if ($cached !== null) { jsonResponse($cached); } } $bookingStats = calculateBookingStats(); $messageStats = calculateMessageStats(); $newsStats = calculateNewsStats(); $subscriberStats = calculateSubscriberStats(); $payload = [ 'success' => true, 'data' => [ 'bookings' => $bookingStats, 'messages' => $messageStats, 'news' => $newsStats, 'subscribers' => $subscriberStats ] ]; setStatsCache($cacheKey, $payload); jsonResponse($payload); } function calculateBookingStats() { global $db; $today = date('Y-m-d'); $weekStart = date('Y-m-d', strtotime('monday this week')); $weekEnd = date('Y-m-d', strtotime('sunday this week')); $totalBookings = $db->count('bookings'); $thisWeekCount = $db->countByDateRange('bookings', 'booking_date', $weekStart, $weekEnd); // Last week's bookings (for trend) $lastWeekStart = date('Y-m-d', strtotime('monday last week')); $lastWeekEnd = date('Y-m-d', strtotime('sunday last week')); $lastWeekCount = $db->countByDateRange('bookings', 'booking_date', $lastWeekStart, $lastWeekEnd); $pendingCount = $db->count('bookings', ['status' => 'pending']); $confirmedCount = $db->count('bookings', ['status' => 'confirmed']); // JSON boolean true is compared as string "true" after JSON_UNQUOTE $availableSlotsCount = $db->countByFieldComparison('availability_slots', 'date', '>=', $today, [ 'is_available' => 'true' ]); $confirmationRate = $totalBookings > 0 ? round(($confirmedCount / $totalBookings) * 100) : 0; // Calculate trend percentages $bookingTrend = $lastWeekCount > 0 ? round((($thisWeekCount - $lastWeekCount) / $lastWeekCount) * 100) : ($thisWeekCount > 0 ? 100 : 0); return [ 'this_week' => $thisWeekCount, 'pending' => $pendingCount, 'confirmed' => $confirmedCount, 'available_slots' => $availableSlotsCount, 'confirmation_rate' => $confirmationRate, 'trend' => $bookingTrend, 'total' => $totalBookings ]; } function calculateMessageStats() { global $db; $total = $db->count('messages'); $unread = $db->count('messages', ['status' => 'unread']); $weekStart = date('Y-m-d', strtotime('monday this week')); $weekEnd = date('Y-m-d', strtotime('sunday this week')); $thisWeek = $db->countByDateRange('messages', 'created_at', $weekStart . ' 00:00:00', $weekEnd . ' 23:59:59'); return [ 'total' => $total, 'unread' => $unread, 'this_week' => $thisWeek ]; } function calculateNewsStats() { global $db; return [ 'total' => $db->count('news'), 'published' => $db->count('news', ['status' => 'published']), 'draft' => $db->count('news', ['status' => 'draft']) ]; } function calculateSubscriberStats() { global $db; return [ 'total' => $db->count('subscribers'), 'active' => $db->count('subscribers', ['status' => 'active']) ]; } function getBookingStats() { $cacheKey = 'stats_bookings_v1'; if (!$GLOBALS['forceRefresh']) { $cached = getStatsCache($cacheKey, 30); if ($cached !== null) { jsonResponse($cached); } } $payload = [ 'success' => true, 'data' => calculateBookingStats() ]; setStatsCache($cacheKey, $payload); jsonResponse($payload); } function getMessageStats() { $cacheKey = 'stats_messages_v1'; if (!$GLOBALS['forceRefresh']) { $cached = getStatsCache($cacheKey, 30); if ($cached !== null) { jsonResponse($cached); } } $payload = [ 'success' => true, 'data' => calculateMessageStats() ]; setStatsCache($cacheKey, $payload); jsonResponse($payload); } function getNewsStats() { $cacheKey = 'stats_news_v1'; if (!$GLOBALS['forceRefresh']) { $cached = getStatsCache($cacheKey, 30); if ($cached !== null) { jsonResponse($cached); } } $payload = [ 'success' => true, 'data' => calculateNewsStats() ]; setStatsCache($cacheKey, $payload); jsonResponse($payload); } function getStatsCache($cacheKey, $ttlSeconds) { $cacheDir = DATA_DIR . 'cache/'; $cacheFile = $cacheDir . 'stats_' . md5($cacheKey) . '.json'; if (!file_exists($cacheFile)) { return null; } $age = time() - (int)filemtime($cacheFile); if ($age > (int)$ttlSeconds) { return null; } $content = @file_get_contents($cacheFile); if ($content === false || $content === '') { return null; } $decoded = json_decode($content, true); return is_array($decoded) ? $decoded : null; } function setStatsCache($cacheKey, $payload) { $cacheDir = DATA_DIR . 'cache/'; if (!is_dir($cacheDir)) { @mkdir($cacheDir, 0755, true); } $cacheFile = $cacheDir . 'stats_' . md5($cacheKey) . '.json'; @file_put_contents($cacheFile, json_encode($payload), LOCK_EX); }