false, 'ERROR' => 'method_not_allowed'], 405); } $channelType = trim($_GET['ChannelType'] ?? ''); $agent = trim($_GET['Agent'] ?? ''); $includeArchived = ($_GET['IncludeArchived'] ?? '0') === '1'; $limit = min(max((int) ($_GET['Limit'] ?? 50), 1), 200); $offset = max((int) ($_GET['Offset'] ?? 0), 0); $where = []; $params = []; if (!$includeArchived) { $where[] = 'c.IsArchived = 0'; } if ($channelType !== '' && in_array($channelType, ['public', 'private', 'direct'], true)) { $where[] = 'c.ChannelType = ?'; $params[] = $channelType; } $join = ''; if ($agent !== '') { $join = 'INNER JOIN Hub_ChannelMembers m ON m.ChannelID = c.ID AND m.AgentAddress = ?'; array_unshift($params, $agent); } $whereClause = count($where) > 0 ? 'WHERE ' . implode(' AND ', $where) : ''; // Count total $countSql = "SELECT COUNT(*) AS cnt FROM Hub_Channels c $join $whereClause"; $countRow = queryOne($countSql, $params); $total = (int) ($countRow['cnt'] ?? 0); // Fetch page $dataSql = "SELECT c.*, (SELECT COUNT(*) FROM Hub_ChannelMembers WHERE ChannelID = c.ID) AS MemberCount FROM Hub_Channels c $join $whereClause ORDER BY c.CreatedAt DESC LIMIT ? OFFSET ?"; $dataParams = array_merge($params, [$limit, $offset]); $rows = queryTimed($dataSql, $dataParams); $channels = []; foreach ($rows as $r) { $channels[] = [ 'ID' => (int) $r['ID'], 'Name' => $r['Name'], 'DisplayName' => $r['DisplayName'], 'Purpose' => $r['Purpose'], 'ChannelType' => $r['ChannelType'], 'CreatedBy' => $r['CreatedBy'], 'IsArchived' => (bool) $r['IsArchived'], 'CreatedAt' => toISO8601($r['CreatedAt']), 'UpdatedAt' => toISO8601($r['UpdatedAt']), 'MemberCount' => (int) $r['MemberCount'], ]; } jsonResponse(['OK' => true, 'Channels' => $channels, 'Total' => $total]);