import 'dart:typed_data'; import 'package:dio/dio.dart'; import '../models/models.dart'; /// High-level API surface that maps 1-to-1 with the player-server REST API /// (see player-server/docs/api.md for the authoritative contract). /// /// Each method corresponds to a single HTTP endpoint. All HTTP plumbing /// (bearer-token injection, 401 → login redirect, base-URL configuration) is /// handled by the [Dio] instance provided at construction time. /// /// In production, create the [Dio] via [DioClient] which wires up the auth /// and 401-redirect interceptors. In tests, pass a plain or mocked [Dio]. /// /// Concrete implementations of the stub methods will be added incrementally as /// features are built. class PlayerApiClient { /// Creates a client backed by [dio]. /// /// Prefer creating [dio] via [DioClient] in production to get bearer-token /// injection and 401 → login redirect out of the box. PlayerApiClient({required Dio dio}) : _dio = dio; // The configured Dio instance with auth/401 interceptors already applied. final Dio _dio; // --------------------------------------------------------------------------- // Auth // --------------------------------------------------------------------------- Future bootstrap({ required String username, required String password, }) => throw UnimplementedError(); Future login({ required String username, required String password, }) => throw UnimplementedError(); Future logout() => throw UnimplementedError(); // --------------------------------------------------------------------------- // Health // --------------------------------------------------------------------------- Future healthz() => throw UnimplementedError(); Future readyz() => throw UnimplementedError(); // --------------------------------------------------------------------------- // Shared / public endpoints (no auth required) // --------------------------------------------------------------------------- Future getSharedMediaPage(String token) => throw UnimplementedError(); Future streamSharedMedia(String token, {String? range}) => throw UnimplementedError(); Future getSharedThumbnail(String token) => throw UnimplementedError(); Future downloadSharedMedia(String token) => throw UnimplementedError(); // --------------------------------------------------------------------------- // Config // --------------------------------------------------------------------------- Future> getConfig() => throw UnimplementedError(); // --------------------------------------------------------------------------- // Sets // --------------------------------------------------------------------------- Future> listSets() => throw UnimplementedError(); Future> browseSet(int setId, {String? parent}) => throw UnimplementedError(); Future getSetCover(int setId, {String? folder}) => throw UnimplementedError(); Future updateSetCover(int setId, {String? folder}) => throw UnimplementedError(); Future uploadToSet( int setId, { required String fileName, required List bytes, }) => throw UnimplementedError(); // --------------------------------------------------------------------------- // Media // --------------------------------------------------------------------------- Future> listMedia({ String? search, int? setId, List? setIds, String? type, bool? favorites, List? tags, double? minDuration, double? maxDuration, int? fileSizeMin, int? fileSizeMax, String? sort, int? limit, int? offset, String? folder, String? parent, }) => throw UnimplementedError(); Future getMedia(int mediaId) => throw UnimplementedError(); Future streamMedia(int mediaId, {String? range}) => throw UnimplementedError(); Future downloadMedia(int mediaId) => throw UnimplementedError(); Future getThumbnail(int mediaId) => throw UnimplementedError(); Future regenerateThumbnail(int mediaId) => throw UnimplementedError(); Future toggleFavorite(int mediaId) => throw UnimplementedError(); Future deleteMedia(int mediaId) => throw UnimplementedError(); Future restoreMedia(int mediaId) => throw UnimplementedError(); // --------------------------------------------------------------------------- // Tags // --------------------------------------------------------------------------- Future> listTags() => throw UnimplementedError(); Future addTag(int mediaId, String tag) => throw UnimplementedError(); Future removeTag(int mediaId, String tag) => throw UnimplementedError(); // --------------------------------------------------------------------------- // Shares // --------------------------------------------------------------------------- Future createShare( int mediaId, { DateTime? expiresAt, int? maxUses, }) => throw UnimplementedError(); Future> listSharesForMedia(int mediaId) => throw UnimplementedError(); Future> listMyShares() => throw UnimplementedError(); Future revokeShare(String token) => throw UnimplementedError(); // --------------------------------------------------------------------------- // Notes // --------------------------------------------------------------------------- Future getNote(int mediaId) => throw UnimplementedError(); Future upsertNote(int mediaId, String content) => throw UnimplementedError(); Future deleteNote(int mediaId) => throw UnimplementedError(); // --------------------------------------------------------------------------- // Progress // --------------------------------------------------------------------------- Future updateProgress({ required int mediaId, required double positionSeconds, }) => throw UnimplementedError(); Future updateProgressStatus({ required int mediaId, required String status, }) => throw UnimplementedError(); Future> listInProgress() => throw UnimplementedError(); // --------------------------------------------------------------------------- // Podcasts // --------------------------------------------------------------------------- Future> listPodcasts() => throw UnimplementedError(); Future> listEpisodes( int podcastSetId, { int? limit, int? offset, }) => throw UnimplementedError(); Future downloadEpisode(int episodeId) => throw UnimplementedError(); Future toggleEpisodeComplete(int episodeId) => throw UnimplementedError(); Future subscribePodcast({ required String feedUrl, String? setName, }) => throw UnimplementedError(); // --------------------------------------------------------------------------- // Admin – Users // --------------------------------------------------------------------------- Future> listUsers() => throw UnimplementedError(); Future createUser({ required String username, required String password, required bool isAdmin, }) => throw UnimplementedError(); Future deleteUser(int userId) => throw UnimplementedError(); // --------------------------------------------------------------------------- // Admin – Permissions // --------------------------------------------------------------------------- Future>> listPermissions() => throw UnimplementedError(); Future grantPermission({ required int setId, required int userId, required String role, }) => throw UnimplementedError(); Future revokePermission({ required int setId, required int userId, }) => throw UnimplementedError(); // --------------------------------------------------------------------------- // Admin – Scanner // --------------------------------------------------------------------------- Future triggerRescan() => throw UnimplementedError(); Future> getScanProgress() => throw UnimplementedError(); Future> listTrash() => throw UnimplementedError(); // Expose the underlying Dio for advanced callers (e.g. binary streaming). // This should not be used for ordinary JSON requests; prefer the typed // methods above. Dio get rawDio => _dio; }