import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:supabase_flutter/supabase_flutter.dart'; import 'supabase_provider.dart'; import '../utils/app_time.dart'; /// Admin user query parameters for server-side pagination. class AdminUserQuery { /// Creates admin user query parameters. const AdminUserQuery({ this.offset = 0, this.limit = 50, this.searchQuery = '', }); /// Offset for pagination. final int offset; /// Number of items per page (default: 50). final int limit; /// Full text search query. final String searchQuery; AdminUserQuery copyWith({ int? offset, int? limit, String? searchQuery, }) { return AdminUserQuery( offset: offset ?? this.offset, limit: limit ?? this.limit, searchQuery: searchQuery ?? this.searchQuery, ); } } final adminUserQueryProvider = StateProvider((ref) => const AdminUserQuery()); final adminUserControllerProvider = Provider((ref) { final client = ref.watch(supabaseClientProvider); return AdminUserController(client); }); class AdminUserStatus { AdminUserStatus({required this.email, required this.bannedUntil}); final String? email; final DateTime? bannedUntil; bool get isLocked { if (bannedUntil == null) return false; return bannedUntil!.isAfter(AppTime.now()); } } class AdminUserController { AdminUserController(this._client); final SupabaseClient _client; Future updateProfile({ required String userId, required String fullName, required String role, }) async { await _client .from('profiles') .update({'full_name': fullName, 'role': role}) .eq('id', userId); } Future updateRole({ required String userId, required String role, }) async { await _client.from('profiles').update({'role': role}).eq('id', userId); } Future setPassword({ required String userId, required String password, }) async { await _invokeAdminFunction( action: 'set_password', payload: {'userId': userId, 'password': password}, ); } Future setLock({required String userId, required bool locked}) async { await _invokeAdminFunction( action: 'set_lock', payload: {'userId': userId, 'locked': locked}, ); } Future fetchStatus(String userId) async { final data = await _invokeAdminFunction( action: 'get_user', payload: {'userId': userId}, ); final user = (data as Map)['user'] as Map; final bannedUntilRaw = user['banned_until'] as String?; final bannedUntilParsed = bannedUntilRaw == null ? null : DateTime.tryParse(bannedUntilRaw); return AdminUserStatus( email: user['email'] as String?, bannedUntil: bannedUntilParsed == null ? null : AppTime.toAppTime(bannedUntilParsed), ); } Future _invokeAdminFunction({ required String action, required Map payload, }) async { final response = await _client.functions.invoke( 'admin_user_management', body: {'action': action, ...payload}, ); if (response.status != 200) { throw Exception(_extractErrorMessage(response.data)); } return response.data; } String _extractErrorMessage(dynamic data) { if (data is Map) { final error = data['error']; if (error is String && error.trim().isNotEmpty) { return error; } final message = data['message']; if (message is String && message.trim().isNotEmpty) { return message; } } return 'Admin request failed.'; } }