import 'package:finlytic_app/core/network/api_client.dart'; import 'package:finlytic_app/core/network/signalr_service.dart'; import 'package:finlytic_app/features/news/models/news_article_model.dart'; class NewsRepository { final ApiClient apiClient; final String backendUrl; /// Central Real-Time WebSocket service (shared, authenticated `/hubs/news` connection). /// May be null for call-sites that only need REST access (e.g. one-off dialogs) and /// don't require the live feed; in that case [liveNewsStream] yields no events. final SignalRService? signalRService; NewsRepository({ required this.apiClient, required this.backendUrl, this.signalRService, }); /// Live news articles pushed by the central SignalRService's `/hubs/news` connection. /// The connection itself is established centrally (see `SignalRService.initSignalR()`), /// so this repository only maps the already-authenticated stream to typed models. Stream get liveNewsStream { final signalR = signalRService; if (signalR == null) return const Stream.empty(); return signalR.newsArticleStream.map(NewsArticleModel.fromJson); } Future> fetchNews({ int page = 1, int pageSize = 20, String? symbol, String? isin, String? date, String? query, bool? hasSentiment, }) async { try { final Map queryParams = { 'page': page, 'pageSize': pageSize, }; if (symbol != null && symbol.isNotEmpty) queryParams['symbol'] = symbol; if (isin != null && isin.isNotEmpty) queryParams['isin'] = isin; if (date != null && date.isNotEmpty) queryParams['date'] = date; if (query != null && query.isNotEmpty) queryParams['query'] = query; if (hasSentiment == true) queryParams['hasSentiment'] = true; final response = await apiClient.get('/api/v1/news', queryParameters: queryParams); if (response.statusCode == 200 && response.data is List) { final List data = response.data; return data .whereType>() .map((json) => NewsArticleModel.fromJson(json)) .toList(); } return []; } catch (e) { throw Exception('Failed to load news: $e'); } } Future reanalyzeArticle(String articleId) async { try { final response = await apiClient.post('/api/v1/news/sentiment/article/$articleId/analyze'); if (response.statusCode == 200 && response.data != null) { final Map data = response.data is Map ? Map.from(response.data) : {}; return NewsArticleModel.fromJson(data); } throw Exception('Unerwartete Server-Antwort'); } catch (e) { throw Exception('Sentiment-Analyse fehlgeschlagen: $e'); } } /// No-op: the underlying `/hubs/news` WebSocket connection is owned and /// lifecycle-managed centrally by [SignalRService] (started once in /// `main.dart` after authentication), so this repository has nothing of /// its own to dispose. void dispose() {} }