import 'dart:typed_data'; import 'package:supabase_flutter/supabase_flutter.dart'; import '../../domain/models/profile_model.dart'; import '../../domain/models/profile_stats_model.dart'; class ProfileService { const ProfileService(this._client); final SupabaseClient _client; User get _currentUser { final user = _client.auth.currentUser; if (user == null) { throw StateError('No authenticated user'); } return user; } Future fetchMyProfile() async { final user = _currentUser; final response = await _client .from('profiles') .select() .eq('user_id', user.id) .maybeSingle(); if (response == null) { final created = await _client .from('profiles') .insert({ 'user_id': user.id, 'username': (user.userMetadata?['username'] as String?) ?? '', 'bio': '', 'avatar_url': '', }) .select() .single(); return ProfileModel.fromJson(created); } return ProfileModel.fromJson(response); } Future updateUsername(String username) async { final user = _currentUser; await _client.auth.updateUser(UserAttributes(data: {'username': username})); final updated = await _client .from('profiles') .update({'username': username}) .eq('user_id', user.id) .select() .single(); return ProfileModel.fromJson(updated); } Future updateBio(String bio) async { final user = _currentUser; final updated = await _client .from('profiles') .update({'bio': bio}) .eq('user_id', user.id) .select() .single(); return ProfileModel.fromJson(updated); } Future updateProfile({ required String username, required String bio, }) async { final user = _currentUser; await _client.auth.updateUser(UserAttributes(data: {'username': username})); final updated = await _client .from('profiles') .update({ 'username': username, 'bio': bio, }) .eq('user_id', user.id) .select() .single(); return ProfileModel.fromJson(updated); } Future uploadAvatar({ required Uint8List bytes, required String extension, }) async { final user = _currentUser; final path = 'avatars/${user.id}/${DateTime.now().millisecondsSinceEpoch}.$extension'; await _client.storage.from('avatars').uploadBinary( path, bytes, fileOptions: const FileOptions(upsert: true), ); final avatarUrl = _client.storage.from('avatars').getPublicUrl(path); final updated = await _client .from('profiles') .update({'avatar_url': avatarUrl}) .eq('user_id', user.id) .select() .single(); return ProfileModel.fromJson(updated); } Future fetchMyStats() async { final user = _currentUser; final postResponse = await _client .from('posts') .select('*') .eq('user_id', user.id); final commentResponse = await _client .from('comments') .select('*') .eq('user_id', user.id); final trackResponse = await _client .from('tracks') .select('*') .eq('user_id', user.id); return ProfileStatsModel( postsCount: (postResponse as List).length, commentsCount: (commentResponse as List).length, tracksCount: (trackResponse as List).length, ); } }