import 'dart:async'; // Serve per il Timer del debounce import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:flux/core/blocs/session/session_cubit.dart'; import 'package:flux/features/customers/data/customer_repository.dart'; import 'package:flux/features/customers/models/customer_model.dart'; import 'package:get_it/get_it.dart'; part 'customer_state.dart'; class CustomerCubit extends Cubit { final CustomerRepository _repository = GetIt.I(); final SessionCubit _sessionCubit = GetIt.I(); // Variabile per gestire il debounce della ricerca Timer? _searchDebounce; CustomerCubit() : super(const CustomerState()); // --- LETTURA --- Future loadCustomers() async { emit(state.copyWith(status: CustomerStatus.loading)); try { final customers = await _repository.getCustomers( _sessionCubit.state.company!.id!, ); emit( state.copyWith(status: CustomerStatus.success, customers: customers), ); } catch (e) { emit( state.copyWith( status: CustomerStatus.failure, errorMessage: e.toString(), ), ); } } // --- CREAZIONE --- Future createCustomer(CustomerModel customer) async { emit(state.copyWith(status: CustomerStatus.loading)); try { final newCustomer = await _repository.saveCustomer(customer); // Aggiorniamo la lista locale aggiungendo il nuovo cliente in cima final updatedList = List.from(state.customers) ..insert(0, newCustomer); emit( state.copyWith( status: CustomerStatus.success, customers: updatedList, lastCreatedCustomer: newCustomer, ), ); } catch (e) { emit( state.copyWith( status: CustomerStatus.failure, errorMessage: e.toString(), ), ); } } // --- AGGIORNAMENTO --- Future updateCustomer(CustomerModel customer) async { emit(state.copyWith(status: CustomerStatus.loading)); try { final updatedCustomer = await _repository.updateCustomer(customer); final updatedList = List.from(state.customers); final index = updatedList.indexWhere((c) => c.id == updatedCustomer.id); if (index != -1) { updatedList[index] = updatedCustomer; } emit( state.copyWith( status: CustomerStatus.success, customers: updatedList, lastCreatedCustomer: updatedCustomer, // Utile se modifichi un cliente appena creato ), ); } catch (e) { emit( state.copyWith( status: CustomerStatus.failure, errorMessage: e.toString(), ), ); } } // --- RICERCA CON DEBOUNCE --- void searchCustomers(String query) { // 1. Se c'è già una ricerca in attesa (l'utente sta digitando veloce), la annulliamo if (_searchDebounce?.isActive ?? false) _searchDebounce!.cancel(); // 2. Facciamo partire un timer di 400 millisecondi _searchDebounce = Timer(const Duration(milliseconds: 300), () async { // Se cancella tutto e la query è vuota, ricarichiamo la lista base if (query.trim().isEmpty) { await loadCustomers(); return; } // Nessun "loading" state qui, per evitare sfarfallii visivi mentre si scrive try { final results = await _repository.searchCustomers( _sessionCubit.state.company!.id!, query, ); emit( state.copyWith(status: CustomerStatus.success, customers: results), ); } catch (e) { emit( state.copyWith( status: CustomerStatus.failure, errorMessage: e.toString(), ), ); } }); } Future quickCreateCustomer({ required String name, String? phone, String? email, }) async { final newCustomer = CustomerModel( name: name, phoneNumber: phone ?? '', email: email ?? '', companyId: _sessionCubit.state.company!.id!, note: '', ); try { final saved = await _repository.saveCustomer(newCustomer); // Lo aggiungiamo in cima ai suggerimenti emit(state.copyWith(customers: [saved, ...state.customers])); return saved; } catch (e) { return null; } } // Pulizia della memoria quando il Cubit viene distrutto @override Future close() { _searchDebounce?.cancel(); return super.close(); } }