import 'package:flutter/foundation.dart'; import 'package:flux/core/enums_and_consts/consts.dart'; import 'package:flux/features/master_data/staff/models/staff_member_model.dart'; import 'package:flux/features/master_data/store/models/store_model.dart'; import 'package:get_it/get_it.dart'; import 'package:supabase_flutter/supabase_flutter.dart'; class StaffRepository { final SupabaseClient _supabase = GetIt.I.get(); // --- ANAGRAFICA PURA --- // Prende tutto lo staff della Company (per l'Hub Anagrafiche) Future> getStaffMembers( String companyId, { String? storeId, }) async { try { var filterBuilder = _supabase .from(Tables.staffMembers) .select(''' *, store_assignments:${Tables.staffInStores} ( ${Tables.stores}(*) ) ''') .eq('company_id', companyId); if (storeId != null) { filterBuilder = filterBuilder.or( 'store_id.eq.$storeId,store_id.is.null', ); } var transformBuilder = filterBuilder.order('name', ascending: true); final response = await transformBuilder; return (response as List) .map((s) => StaffMemberModel.fromMap(s)) .toList(); } on Exception catch (e) { debugPrint('Errore nel recupero della lista di staff: $e'); throw Exception('Errore nel recupero della lista di staff: $e'); } } Future getStaffMemberById(String staffId) async { try { final response = await _supabase .from(Tables.staffMembers) .select(''' *, store_assignments:${Tables.staffInStores} ( ${Tables.stores}(*) ) ''') .eq('id', staffId) .single(); return StaffMemberModel.fromMap(response); } on Exception catch (e) { throw ('Errore nel recupero del membro staff con ID $staffId: $e'); } } Future saveStaffMember(StaffMemberModel member) async { final response = await _supabase .from(Tables.staffMembers) .upsert(member.toMap()) .select() .single(); return StaffMemberModel.fromMap(response); } // --- LOGICA DI INVITO (Tramite Edge Function) --- Future inviteStaffMember(StaffMemberModel newMember) async { if (newMember.email == null || newMember.email!.isEmpty) { throw Exception( "L'indirizzo email รจ obbligatorio per invitare un collega.", ); } try { final response = await _supabase.functions.invoke( 'invite_staff', body: newMember.toMap(), ); if (response.status != 200) { throw Exception("Errore dal server: ${response.data}"); } // La funzione ci restituisce l'ID fresco di database! final responseData = response.data as Map; return responseData['user_id'] as String; } on FunctionException catch (e) { throw Exception( "Errore di comunicazione con il server: ${e.reasonPhrase}", ); } catch (e) { throw Exception("Impossibile invitare il collega: $e"); } } Future resetPassword(String email) async { try { final response = await Supabase.instance.client.functions.invoke( 'reset_password', body: {'email': email.trim()}, ); if (response.status != 200) { throw Exception(response.data['error'] ?? "Errore sconosciuto"); } } catch (e) { throw Exception("Errore nell'invio del link: $e"); } } // --- LOGICA DI GIUNZIONE (Staff <-> Store) --- // Recupera i membri assegnati a uno specifico negozio // Qui facciamo una JOIN per avere i dati del membro partendo dalla tabella di giunzione Future> getStaffMembersInStore(String storeId) async { final response = await _supabase .from(Tables.staffInStores) .select( '${Tables.staffMembers} (*)', ) // Prende tutti i campi della tabella staff_member collegata .eq('store_id', storeId); return (response as List) .map((item) => StaffMemberModel.fromMap(item[Tables.staffMembers])) .toList(); } // Recupera i negozi assegnati a uno specifico membro // Qui facciamo una JOIN per avere i dati del membro partendo dalla tabella di giunzione Future> getStaffMemberStore(String staffId) async { final response = await _supabase .from(Tables.staffInStores) .select( '${Tables.stores} (*)', ) // Prende tutti i campi della tabella store collegata .eq('staff_member_id', staffId); return (response as List) .map((item) => StoreModel.fromMap(item[Tables.stores])) .toList(); } // Assegna un membro a un negozio Future assignStaffToStore(String staffId, String storeId) async { await _supabase.from(Tables.staffInStores).insert({ 'staff_member_id': staffId, 'store_id': storeId, }); } // Rimuove l'assegnazione Future removeStaffFromStore(String staffId, String storeId) async { await _supabase .from(Tables.staffInStores) .delete() .eq('staff_member_id', staffId) .eq('store_id', storeId); } // Nel StaffRepository // Utility per pulire le assegnazioni esistenti prima di riscriverle Future clearStoreAssignments(String staffId) async { await _supabase .from(Tables.staffInStores) .delete() .eq('staff_member_id', staffId); } }