import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'dart:convert'; /// Watch history state - tracks which content has been watched class WatchHistory { /// Set of watched movie IDs final Set watchedMovies; /// Set of watched episode IDs (format: seriesId_seasonNum_episodeNum) final Set watchedEpisodes; const WatchHistory({ this.watchedMovies = const {}, this.watchedEpisodes = const {}, }); WatchHistory copyWith({ Set? watchedMovies, Set? watchedEpisodes, }) { return WatchHistory( watchedMovies: watchedMovies ?? this.watchedMovies, watchedEpisodes: watchedEpisodes ?? this.watchedEpisodes, ); } /// Check if a movie has been watched bool isMovieWatched(String movieId) => watchedMovies.contains(movieId); /// Check if an episode has been watched bool isEpisodeWatched(String episodeId) => watchedEpisodes.contains(episodeId); /// Generate episode key static String episodeKey(String seriesId, int seasonNum, int episodeNum) { return '${seriesId}_${seasonNum}_$episodeNum'; } } /// Watch history notifier with persistence class WatchHistoryNotifier extends StateNotifier { static const String _moviesKey = 'watch_history_movies'; static const String _episodesKey = 'watch_history_episodes'; SharedPreferences? _prefs; bool _initialized = false; WatchHistoryNotifier() : super(const WatchHistory()) { _loadHistory(); } Future _loadHistory() async { if (_initialized) return; try { _prefs = await SharedPreferences.getInstance(); final moviesJson = _prefs?.getString(_moviesKey); final episodesJson = _prefs?.getString(_episodesKey); final movies = moviesJson != null ? Set.from(jsonDecode(moviesJson) as List) : {}; final episodes = episodesJson != null ? Set.from(jsonDecode(episodesJson) as List) : {}; state = WatchHistory( watchedMovies: movies, watchedEpisodes: episodes, ); _initialized = true; print('Watch history loaded: ${movies.length} movies, ${episodes.length} episodes'); } catch (e) { print('Error loading watch history: $e'); } } Future _saveMovies() async { try { _prefs ??= await SharedPreferences.getInstance(); await _prefs?.setString(_moviesKey, jsonEncode(state.watchedMovies.toList())); } catch (e) { print('Error saving movie watch history: $e'); } } Future _saveEpisodes() async { try { _prefs ??= await SharedPreferences.getInstance(); await _prefs?.setString(_episodesKey, jsonEncode(state.watchedEpisodes.toList())); } catch (e) { print('Error saving episode watch history: $e'); } } /// Mark a movie as watched void markMovieWatched(String movieId) { final newSet = Set.from(state.watchedMovies)..add(movieId); state = state.copyWith(watchedMovies: newSet); _saveMovies(); } /// Mark a movie as unwatched void markMovieUnwatched(String movieId) { final newSet = Set.from(state.watchedMovies)..remove(movieId); state = state.copyWith(watchedMovies: newSet); _saveMovies(); } /// Toggle movie watched status void toggleMovieWatched(String movieId) { if (state.isMovieWatched(movieId)) { markMovieUnwatched(movieId); } else { markMovieWatched(movieId); } } /// Mark an episode as watched void markEpisodeWatched(String episodeKey) { final newSet = Set.from(state.watchedEpisodes)..add(episodeKey); state = state.copyWith(watchedEpisodes: newSet); _saveEpisodes(); } /// Mark an episode as unwatched void markEpisodeUnwatched(String episodeKey) { final newSet = Set.from(state.watchedEpisodes)..remove(episodeKey); state = state.copyWith(watchedEpisodes: newSet); _saveEpisodes(); } /// Toggle episode watched status void toggleEpisodeWatched(String episodeKey) { if (state.isEpisodeWatched(episodeKey)) { markEpisodeUnwatched(episodeKey); } else { markEpisodeWatched(episodeKey); } } /// Clear all watch history void clearAll() { state = const WatchHistory(); _saveMovies(); _saveEpisodes(); } } /// Provider for watch history final watchHistoryProvider = StateNotifierProvider((ref) { return WatchHistoryNotifier(); });