import 'dart:convert'; import '../utils/app_logger.dart'; import 'plex_auth_service.dart'; import 'storage_service.dart'; /// Centralized server configuration registry /// Manages which servers are available and their configurations class ServerRegistry { final StorageService _storage; ServerRegistry(this._storage); /// Get all registered servers Future> getServers() async { try { final serversJson = _storage.getServersListJson(); if (serversJson == null || serversJson.isEmpty) { return []; } final List serversList = jsonDecode(serversJson); return serversList.map((json) => PlexServer.fromJson(json as Map)).toList(); } catch (e, stackTrace) { appLogger.e('Failed to load servers from storage', error: e, stackTrace: stackTrace); return []; } } /// Save all servers to storage Future saveServers(List servers) async { try { final serversJson = jsonEncode(servers.map((s) => s.toJson()).toList()); await _storage.saveServersListJson(serversJson); appLogger.d('Saved ${servers.length} servers to storage'); } catch (e, stackTrace) { appLogger.e('Failed to save servers to storage', error: e, stackTrace: stackTrace); rethrow; } } /// Get a specific server by ID Future getServer(String serverId) async { final servers = await getServers(); try { return servers.firstWhere((s) => s.clientIdentifier == serverId); } catch (e) { return null; } } /// Update server status (called when server connection status changes) Future updateServerStatus(String serverId) async { final servers = await getServers(); final serverIndex = servers.indexWhere((s) => s.clientIdentifier == serverId); if (serverIndex == -1) { appLogger.w('Server not found for status update: $serverId'); return; } // Note: PlexServer from auth service doesn't have mutable status fields // Status tracking is handled by MultiServerManager // This method is kept for future extension if we add status to PlexServer model } /// Add or update a single server Future upsertServer(PlexServer server) async { final servers = await getServers(); final index = servers.indexWhere((s) => s.clientIdentifier == server.clientIdentifier); if (index >= 0) { servers[index] = server; appLogger.d('Updated server: ${server.name}'); } else { servers.add(server); appLogger.d('Added new server: ${server.name}'); } await saveServers(servers); } /// Remove a server Future removeServer(String serverId) async { final servers = await getServers(); servers.removeWhere((s) => s.clientIdentifier == serverId); await saveServers(servers); appLogger.i('Removed server: $serverId'); } /// Clear all servers Future clearAllServers() async { await _storage.clearServersList(); appLogger.i('Cleared all servers from registry'); } /// Refresh servers from Plex API and update storage /// This updates connection info (IPs, ports) that may have changed Future refreshServersFromApi() async { final token = _storage.getPlexToken(); if (token == null || token.isEmpty) { appLogger.d('No Plex token available, skipping server refresh'); return; } try { appLogger.d('Refreshing servers from Plex API...'); final authService = await PlexAuthService.create(); final freshServers = await authService.fetchServers(token); if (freshServers.isEmpty) { appLogger.w('API returned no servers, keeping existing data'); return; } // Get existing servers to preserve any local-only data final existingServers = await getServers(); final existingIds = existingServers.map((s) => s.clientIdentifier).toSet(); // Update existing servers with fresh connection info, add new ones final updatedServers = []; for (final fresh in freshServers) { if (existingIds.contains(fresh.clientIdentifier)) { // Server exists - use fresh data (updated IPs, connections) updatedServers.add(fresh); } else { // New server - add it updatedServers.add(fresh); appLogger.i('Discovered new server: ${fresh.name}'); } } await saveServers(updatedServers); appLogger.i('Refreshed ${updatedServers.length} servers from API'); } catch (e, stackTrace) { appLogger.w('Failed to refresh servers from API, using cached data', error: e, stackTrace: stackTrace); // Don't rethrow - we can continue with cached servers } } }