import 'dart:math'; import 'dart:typed_data'; import 'package:supabase_flutter/supabase_flutter.dart'; import '../../domain/models/track_model.dart'; class MusicService { const MusicService(this._client); final SupabaseClient _client; User get _currentUser { final user = _client.auth.currentUser; if (user == null) { throw StateError('No authenticated user'); } return user; } /// Uploads a new track with an MP3 file and metadata. Future uploadTrack({ required Uint8List bytes, required String title, required String genreTag, required String extension, }) async { final user = _currentUser; final ts = DateTime.now().millisecondsSinceEpoch; final random = Random().nextInt(99999); final fileName = '$ts-$random.$extension'; final path = 'tracks/${user.id}/$fileName'; // Upload audio to Supabase Storage await _client.storage.from('tracks').uploadBinary( path, bytes, fileOptions: const FileOptions(upsert: false), ); final audioUrl = _client.storage.from('tracks').getPublicUrl(path); // Insert track record into PostgreSQL await _client.from('tracks').insert({ 'user_id': user.id, 'title': title.trim().isEmpty ? 'UNTITLED' : title.trim().toUpperCase(), 'audio_url': audioUrl, 'genre_tag': genreTag.trim().isEmpty ? 'UNKNOWN' : genreTag.trim().toUpperCase(), 'plays': 0, }); } /// Lists all tracks in chronological order. Future> fetchTracks() async { final response = await _client .from('tracks') .select('*, profiles(username)') .order('created_at', ascending: false); return List>.from(response).map((row) { final username = (row['profiles'] as Map?)?['username'] as String?; return TrackModel.fromJson(row, username: username); }).toList(); } /// Increments the play count of a track. Future incrementPlays(String trackId) async { await _client.rpc('increment_track_plays', params: {'track_id': trackId}); } /// Fetches tracks for a specific user. Future> fetchUserTracks(String userId) async { final response = await _client .from('tracks') .select('*, profiles(username)') .eq('user_id', userId) .order('created_at', ascending: false); return List>.from(response).map((row) { final username = (row['profiles'] as Map?)?['username'] as String?; return TrackModel.fromJson(row, username: username); }).toList(); } }