import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../core/models/playlist_config.dart'; import '../../core/models/iptv_models.dart' as model; import '../../features/iptv/services/xtream_service_mobile.dart'; /// Mobile-specific Xtream service provider import 'package:path_provider/path_provider.dart'; final mobileXtreamServiceProvider = FutureProvider.family( (ref, playlist) async { final dir = await getApplicationDocumentsDirectory(); final service = XtreamServiceMobile(dir.path); await service .setPlaylistAsync(playlist); // Async to resolve DNS before API calls return service; }); /// Mobile-specific live channels provider /// Loads ALL channels from ALL categories final mobileLiveChannelsProvider = FutureProvider.family, PlaylistConfig>( (ref, playlist) async { final service = await ref.watch(mobileXtreamServiceProvider(playlist).future); // Strategy: Try to load categories first (with timeout) // If categories load successfully, load channels for each category // If categories fail/timeout, load all channels at once List categories = []; try { categories = await service.getLiveCategories(); } catch (e) { // Silently fall back to loading all channels } if (categories.isNotEmpty) { // Load channels from each category and combine them final allChannels = []; for (final category in categories) { final channels = await service.getLiveChannels(category.categoryId); allChannels.addAll(channels); } return allChannels; } // Fallback: Load all channels without category filter return service.getLiveChannels(""); }); /// Mobile-specific movies provider final mobileMoviesProvider = FutureProvider.family, PlaylistConfig>((ref, playlist) async { final service = await ref.watch(mobileXtreamServiceProvider(playlist).future); return service.getMoviesByCategory(""); // Fetch all or default }); /// Mobile-specific series pagination provider final mobileSeriesProvider = FutureProvider.family, PlaylistConfig>((ref, playlist) async { final service = await ref.watch(mobileXtreamServiceProvider(playlist).future); return service.getSeriesPaginated(); }); /// Series info with playlist context class SeriesInfoRequest { final PlaylistConfig playlist; final String seriesId; SeriesInfoRequest({required this.playlist, required this.seriesId}); @override bool operator ==(Object other) => identical(this, other) || other is SeriesInfoRequest && runtimeType == other.runtimeType && playlist == other.playlist && seriesId == other.seriesId; @override int get hashCode => playlist.hashCode ^ seriesId.hashCode; } final mobileSeriesInfoByPlaylistProvider = FutureProvider.family((ref, request) async { final service = await ref.watch(mobileXtreamServiceProvider(request.playlist).future); return service.getSeriesInfo(request.seriesId); }); // UI State Provider for persistent navigation final mobileLiveTvUiStateProvider = StateProvider((ref) => LiveTvUiState()); class LiveTvUiState { final String? selectedCategory; final bool isCategoryView; LiveTvUiState({this.selectedCategory, this.isCategoryView = true}); LiveTvUiState copyWith({String? selectedCategory, bool? isCategoryView}) { return LiveTvUiState( selectedCategory: selectedCategory ?? this.selectedCategory, isCategoryView: isCategoryView ?? this.isCategoryView, ); } } /// Persistent index for mobile dashboard navigation final mobileDashboardIndexProvider = StateProvider((ref) => 0); /// Batch EPG provider class BatchEpgRequest { final PlaylistConfig playlist; final List streamIds; BatchEpgRequest({required this.playlist, required this.streamIds}); @override bool operator ==(Object other) => identical(this, other) || other is BatchEpgRequest && runtimeType == other.runtimeType && playlist == other.playlist && streamIds.toSet().toString() == other.streamIds.toSet().toString(); @override int get hashCode => playlist.hashCode ^ streamIds.toSet().toString().hashCode; } /// Load EPG data for multiple streams in one batch request final mobileBatchEpgProvider = FutureProvider.family, BatchEpgRequest>( (ref, request) async { if (request.streamIds.isEmpty) return {}; final service = await ref.watch(mobileXtreamServiceProvider(request.playlist).future); return service.getBatchEPG(request.streamIds); });