import 'package:dio/dio.dart'; import '../../models/playlist.dart'; /// Wire shape for GET /api/playlists. Server splits owned vs. public so /// the UI can present them as different sections; we preserve that split /// to give the integrations page room to grow. class PlaylistsList { const PlaylistsList({required this.owned, required this.public}); final List owned; final List public; factory PlaylistsList.empty() => const PlaylistsList(owned: [], public: []); /// Concatenated view for callers that don't care about the split. List get all => [...owned, ...public]; } class PlaylistsApi { PlaylistsApi(this._dio); final Dio _dio; /// GET /api/playlists?kind=user|system|all. Server returns /// `{"owned": [...], "public": [...]}`. Owned is the caller's own /// playlists, filtered by the kind param (default "user"). Public /// is other users' shared playlists; not filtered by kind. Future list({String kind = 'user'}) async { final r = await _dio.get>( '/api/playlists', queryParameters: {'kind': kind}, ); final body = r.data ?? const {}; List parse(String key) { final raw = (body[key] as List?) ?? const []; return raw .map((e) => Playlist.fromJson((e as Map).cast())) .toList(growable: false); } return PlaylistsList(owned: parse('owned'), public: parse('public')); } Future get(String id) async { final r = await _dio.get>('/api/playlists/$id'); return PlaylistDetail.fromJson(r.data ?? const {}); } /// GET /api/playlists/system/{kind}/shuffle (#415 / #411 R2). /// Same shape as get() but tracks are server-ordered rotation-aware /// (unplayed-this-rotation first; resets when exhausted). {kind} is /// the raw system_variant. Intentionally uncached — varies per play. Future systemShuffle(String variant) async { final r = await _dio.get>( '/api/playlists/system/$variant/shuffle', ); return PlaylistDetail.fromJson(r.data ?? const {}); } /// POST /api/playlists/{id}/tracks. Owner only; server returns the /// playlist detail with the new rows. Future appendTracks(String playlistId, List trackIds) async { await _dio.post( '/api/playlists/$playlistId/tracks', data: {'track_ids': trackIds}, ); } /// POST /api/playlists/system/{kind}/refresh (#411 R2). Rebuilds /// the caller's system playlists and returns the named kind's new /// playlist id, or null when the library is empty. {kind} is the /// raw system_variant — the server routes generically off the /// kind registry, no hyphen mapping. Future refreshSystem(String variant) async { final r = await _dio.post>( '/api/playlists/system/$variant/refresh', data: const {}, ); return (r.data ?? const {})['playlist_id'] as String?; } }