import 'dart:convert'; import 'package:http/http.dart' as http; class EdgeRegistryView { final String edgeId; final String edgeName; final String version; final List capabilities; final String protocol; final bool connected; final DateTime lastSeen; EdgeRegistryView({ required this.edgeId, required this.edgeName, required this.version, required this.capabilities, required this.protocol, required this.connected, required this.lastSeen, }); factory EdgeRegistryView.fromJson(Map json) { return EdgeRegistryView( edgeId: json['edge_id'] as String? ?? '', edgeName: json['edge_name'] as String? ?? '', version: json['version'] as String? ?? '', capabilities: List.from(json['capabilities'] ?? []), protocol: json['protocol'] as String? ?? '', connected: json['connected'] as bool? ?? false, lastSeen: json['last_seen'] != null ? DateTime.parse(json['last_seen'] as String) : DateTime.now(), ); } } class AdapterSummaryView { final String type; final bool enabled; AdapterSummaryView({required this.type, required this.enabled}); factory AdapterSummaryView.fromJson(Map json) { return AdapterSummaryView( type: json['type'] as String? ?? '', enabled: json['enabled'] as bool? ?? false, ); } } class NodeConfigSummaryView { final List adapters; final int concurrency; NodeConfigSummaryView({required this.adapters, required this.concurrency}); factory NodeConfigSummaryView.fromJson(Map json) { return NodeConfigSummaryView( adapters: (json['adapters'] as List? ?? []) .map((e) => AdapterSummaryView.fromJson(e as Map)) .toList(), concurrency: json['concurrency'] as int? ?? 0, ); } } class EdgeNodeSnapshotView { final String nodeId; final String alias; final String label; final bool connected; final NodeConfigSummaryView? config; EdgeNodeSnapshotView({ required this.nodeId, required this.alias, required this.label, required this.connected, this.config, }); factory EdgeNodeSnapshotView.fromJson(Map json) { return EdgeNodeSnapshotView( nodeId: json['node_id'] as String? ?? '', alias: json['alias'] as String? ?? '', label: json['label'] as String? ?? '', connected: json['connected'] as bool? ?? false, config: json['config'] != null ? NodeConfigSummaryView.fromJson(json['config'] as Map) : null, ); } } class EdgeStatusResponseView { final String requestId; final String edgeId; final String edgeName; final int observedTimeUnixNano; final List nodes; final Map metadata; final String error; EdgeStatusResponseView({ required this.requestId, required this.edgeId, required this.edgeName, required this.observedTimeUnixNano, required this.nodes, required this.metadata, required this.error, }); factory EdgeStatusResponseView.fromJson(Map json) { return EdgeStatusResponseView( requestId: json['request_id'] as String? ?? '', edgeId: json['edge_id'] as String? ?? '', edgeName: json['edge_name'] as String? ?? '', observedTimeUnixNano: json['observed_time_unix_nano'] as int? ?? 0, nodes: (json['nodes'] as List? ?? []) .map((e) => EdgeNodeSnapshotView.fromJson(e as Map)) .toList(), metadata: Map.from(json['metadata'] ?? {}), error: json['error'] as String? ?? '', ); } } class EdgeNodeEventView { final String edgeId; final String eventId; final String type; final String source; final String nodeId; final String alias; final String reason; final DateTime timestamp; final DateTime receivedAt; final Map metadata; EdgeNodeEventView({ required this.edgeId, required this.eventId, required this.type, required this.source, required this.nodeId, required this.alias, required this.reason, required this.timestamp, required this.receivedAt, required this.metadata, }); factory EdgeNodeEventView.fromJson(Map json) { return EdgeNodeEventView( edgeId: json['edge_id'] as String? ?? '', eventId: json['event_id'] as String? ?? '', type: json['type'] as String? ?? '', source: json['source'] as String? ?? '', nodeId: json['node_id'] as String? ?? '', alias: json['alias'] as String? ?? '', reason: json['reason'] as String? ?? '', timestamp: json['timestamp'] != null ? DateTime.parse(json['timestamp'] as String) : DateTime.now(), receivedAt: json['received_at'] != null ? DateTime.parse(json['received_at'] as String) : DateTime.now(), metadata: Map.from(json['metadata'] ?? {}), ); } } abstract class ControlPlaneStatusRepository { Future> fetchEdges(); Future fetchEdgeStatus(String edgeId); Future> fetchEdgeEvents(String edgeId); } class HttpControlPlaneStatusRepository implements ControlPlaneStatusRepository { final String baseUrl; final http.Client? client; HttpControlPlaneStatusRepository({required this.baseUrl, this.client}); http.Client get _httpClient => client ?? http.Client(); @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(); } }