import 'package:flutter/foundation.dart'; import '../services/melo_cloud_service.dart'; import '../services/navidrome_service.dart'; import 'database.dart'; /// Koordiniert Playlisten- und Favoriten-Operationen; benachrichtigt Listener /// nach jeder Mutation (für Feedback wie SnackBars — die Listen selbst /// beobachten UIs direkt über die watch()-Streams von [MeloDb]). class PlaylistService extends ChangeNotifier { // `this._cloud` würde den öffentlichen Parameternamen `cloud` zu `_cloud` // (privat) ändern und die API brechen. PlaylistService(this.db, {NavidromeService? navidrome, MeloCloudService? cloud}) : _navidrome = navidrome ?? NavidromeService(), // ignore: prefer_initializing_formals _cloud = cloud; final MeloDb db; final NavidromeService _navidrome; /// Optional: ohne Cloud-Zugang entfällt der Sofort-Push stillschweigend. final MeloCloudService? _cloud; Future createPlaylist(String name, {String? description}) async { final id = await db.createPlaylist(name, description: description); notifyListeners(); return id; } Future deletePlaylist(String id) async { await db.deletePlaylist(id); notifyListeners(); } Future addSongToPlaylist(String playlistId, String songId, int position) async { await db.addSongToPlaylist(playlistId, songId, position); notifyListeners(); } Future removeSongFromPlaylist(String playlistId, String songId) async { await db.removeSongFromPlaylist(playlistId, songId); notifyListeners(); } Future reorderSong(String playlistId, String songId, int newPosition) async { await db.reorderPlaylistSong(playlistId, songId, newPosition); notifyListeners(); } Future reorderAll(String playlistId, List orderedSongIds) async { await db.reorderAllPlaylistSongs(playlistId, orderedSongIds); notifyListeners(); } Future toggleFavorite(String songId) async { await db.toggleFavorite(songId); notifyListeners(); await _meldeFavorit(songId); } /// Meldet den neuen Favoriten-Stand sofort an die Melo-Cloud. /// /// Deterministisch (`set:true/false`), nicht als Umschalten: ein /// abweichender Server-Stand darf den Wunsch nicht invertieren. Nur für /// Titel mit cloudId, und Fehler werden still geschluckt — der nächste /// Abgleich pusht additiv nach. Future _meldeFavorit(String songId) async { final cloud = _cloud; if (cloud == null || !cloud.istAngemeldet) return; final cloudId = (await db.songById(songId))?.cloudId; if (cloudId == null) return; final gesetzt = await db.watchIsFavorite(songId).first; try { await cloud.setzeFavorit(cloudId, gesetzt); } catch (e) { debugPrint('Favorit nicht gemeldet: $e'); } } /// Lädt alle Favoriten vom Navidrome-Server und importiert sie lokal. /// Gibt die Anzahl geladen Favoriten zurück oder 0 wenn nicht verbunden. Future syncFavoritesFromServer() async { await _navidrome.ladeGespeicherteZugangsdaten(); if (!_navidrome.istVerbunden) return 0; try { final serverFavorites = await _navidrome.getFavorites(); for (final song in serverFavorites) { // Prüfe ob Song lokal existiert, dann markiere als Favorit final exists = await db.songExists(song.id); if (exists) { await db.setFavorite(song.id, true); } } notifyListeners(); return serverFavorites.length; } catch (e) { debugPrint('Fehler beim Laden von Server-Favoriten: $e'); return 0; } } /// Lädt alle Playlisten vom Navidrome-Server und importiert sie als lokale Playlisten. /// Gibt die Anzahl importierter Playlisten zurück oder 0 wenn nicht verbunden. Future syncPlaylistsFromServer() async { await _navidrome.ladeGespeicherteZugangsdaten(); if (!_navidrome.istVerbunden) return 0; try { final serverPlaylists = await _navidrome.getPlaylists(); int importedCount = 0; for (final playlist in serverPlaylists) { // Lade Songs aus der Server-Playlist final songs = await _navidrome.getPlaylistSongs(playlist.id); if (songs.isEmpty) continue; // Erstelle lokale Playlist mit gleichem Namen final playlistId = await createPlaylist( '🌐 ${playlist.name}', description: playlist.comment, ); // Füge Songs hinzu (nur wenn sie lokal existieren) for (int i = 0; i < songs.length; i++) { final exists = await db.songExists(songs[i].id); if (exists) { await addSongToPlaylist(playlistId, songs[i].id, i); } } importedCount++; } notifyListeners(); return importedCount; } catch (e) { debugPrint('Fehler beim Laden von Server-Playlisten: $e'); return 0; } } }