import 'dart:convert'; import 'package:http/http.dart' as http; import 'control_plane_status_dto.dart'; abstract class ControlPlaneStatusRepository { Future> fetchEdges(); Future fetchEdgeStatus(String edgeId); Future> fetchEdgeEvents(String edgeId); Future fetchFleetStatus(); Future fetchEdgeOperations(String edgeId); Future sendEdgeCommand( String edgeId, String operation, { String? targetSelector, Map? parameters, }); } class HttpControlPlaneStatusRepository implements ControlPlaneStatusRepository { final String baseUrl; final http.Client _client; final bool _ownsClient; HttpControlPlaneStatusRepository({required this.baseUrl, http.Client? client}) : _client = client ?? http.Client(), _ownsClient = client == null; http.Client get _httpClient => _client; void close() { if (_ownsClient) { _client.close(); } } @override Future> fetchEdges() async { final response = await _httpClient.get(Uri.parse('$baseUrl/edges')); if (response.statusCode != 200) { throw Exception('Failed to fetch edges: ${response.statusCode}'); } final body = json.decode(response.body) as Map; final list = body['edges'] as List? ?? []; return list .map((e) => EdgeRegistryView.fromJson(e as Map)) .toList(); } @override Future fetchEdgeStatus(String edgeId) async { final response = await _httpClient.get( Uri.parse('$baseUrl/edges/$edgeId/status'), ); if (response.statusCode != 200) { throw Exception( 'Failed to fetch status for $edgeId: ${response.statusCode}', ); } final body = json.decode(response.body) as Map; return EdgeStatusResponseView.fromJson(body); } @override Future> fetchEdgeEvents(String edgeId) async { final response = await _httpClient.get( Uri.parse('$baseUrl/edges/$edgeId/events'), ); if (response.statusCode != 200) { throw Exception( 'Failed to fetch events for $edgeId: ${response.statusCode}', ); } final body = json.decode(response.body) as Map; final list = body['events'] as List? ?? []; return list .map((e) => EdgeNodeEventView.fromJson(e as Map)) .toList(); } @override Future fetchFleetStatus() async { final response = await _httpClient.get(Uri.parse('$baseUrl/fleet/status')); if (response.statusCode != 200) { throw Exception('Failed to fetch fleet status: ${response.statusCode}'); } final body = json.decode(response.body) as Map; return FleetStatusResponseView.fromJson(body); } @override Future fetchEdgeOperations(String edgeId) async { final response = await _httpClient.get( Uri.parse('$baseUrl/edges/$edgeId/operations'), ); if (response.statusCode != 200) { throw Exception( 'Failed to fetch operations for $edgeId: ${response.statusCode}', ); } final body = json.decode(response.body) as Map; return EdgeOperationsResponseView.fromJson(body); } @override Future sendEdgeCommand( String edgeId, String operation, { String? targetSelector, Map? parameters, }) async { final Map requestBody = {'operation': operation}; if (targetSelector != null) { requestBody['target_selector'] = targetSelector; } if (parameters != null) { requestBody['parameters'] = parameters; } final response = await _httpClient.post( Uri.parse('$baseUrl/edges/$edgeId/commands'), headers: {'Content-Type': 'application/json'}, body: json.encode(requestBody), ); if (response.statusCode != 200 && response.statusCode != 202) { throw Exception( 'Failed to send command to $edgeId: ${response.statusCode}', ); } final body = json.decode(response.body) as Map; return EdgeCommandResponseView.fromJson(body); } }