false, 'ERROR' => 'method_not_allowed'], 405); } $query = trim($_GET['Query'] ?? ''); $channelId = isset($_GET['ChannelID']) ? (int) $_GET['ChannelID'] : null; $limit = min(max((int) ($_GET['Limit'] ?? 25), 1), 100); $offset = max((int) ($_GET['Offset'] ?? 0), 0); if ($query === '') jsonResponse(['OK' => false, 'ERROR' => 'query_required']); $searchTerm = '%' . $query . '%'; // Count total $countSql = "SELECT COUNT(*) as cnt FROM Hub_Messages WHERE Content LIKE ? AND IsDeleted = 0"; $countParams = [$searchTerm]; if ($channelId !== null) { $countSql .= " AND ChannelID = ?"; $countParams[] = $channelId; } $total = (int) (queryOne($countSql, $countParams)['cnt'] ?? 0); // Fetch results $sql = "SELECT m.*, c.Name AS ChannelName, c.DisplayName AS ChannelDisplayName FROM Hub_Messages m JOIN Hub_Channels c ON c.ID = m.ChannelID WHERE m.Content LIKE ? AND m.IsDeleted = 0"; $params = [$searchTerm]; if ($channelId !== null) { $sql .= " AND m.ChannelID = ?"; $params[] = $channelId; } $sql .= " ORDER BY m.CreatedAt DESC LIMIT ? OFFSET ?"; $params[] = $limit; $params[] = $offset; $rows = queryTimed($sql, $params); $messages = []; foreach ($rows as $row) { $messages[] = [ 'ID' => (int) $row['ID'], 'ChannelID' => (int) $row['ChannelID'], 'ChannelName' => $row['ChannelName'], 'ChannelDisplayName' => $row['ChannelDisplayName'], 'SenderAddress' => $row['SenderAddress'], 'Content' => $row['Content'], 'ParentID' => $row['ParentID'] ? (int) $row['ParentID'] : null, 'IsEdited' => (bool) $row['IsEdited'], 'CreatedAt' => toISO8601($row['CreatedAt']), ]; } jsonResponse([ 'OK' => true, 'Messages' => $messages, 'Total' => $total, ]);