import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flux/features/tickets/models/ticket_model.dart'; import 'package:flux/features/tickets/data/ticket_repository.dart'; import 'package:flux/features/tracking/data/tracking_repository.dart'; import 'package:flux/features/tracking/models/tracking_model.dart'; import 'package:get_it/get_it.dart'; import 'ticket_list_state.dart'; class TicketListCubit extends Cubit { final TicketRepository _repository = GetIt.I.get(); final TrackingRepository _trackingRepository = GetIt.I .get(); static const int _limit = 20; // Paginazione a blocchi di 20 TicketListCubit() : super(const TicketListState()) { loadTickets(refresh: true); } /// Recupera i ticket. Se reset = true, svuota la lista e riparte da offset 0. Future loadTickets({bool refresh = false}) async { if (state.isLoading) return; if (!refresh && state.hasReachedMax) return; emit( state.copyWith( isLoading: true, errorMessage: '', tickets: refresh ? [] : state.tickets, ), ); try { final currentOffset = refresh ? 0 : state.tickets.length; final newTickets = await _repository.fetchStoreTickets( offset: currentOffset, limit: _limit, searchTerm: state.searchTerm, dateRange: state.dateRange, statusFilter: state.statusFilter, ticketTypeFilter: state.ticketTypeFilter, staffIdFilter: state.staffIdFilter, ); emit( state.copyWith( tickets: refresh ? newTickets : [...state.tickets, ...newTickets], isLoading: false, hasReachedMax: newTickets.length < _limit, ), ); } catch (e) { emit(state.copyWith(isLoading: false, errorMessage: e.toString())); } } /// Aggiorna i filtri e ricarica tutto da zero void updateFilters({ String? searchTerm, DateTimeRange? dateRange, TicketStatus? statusFilter, TicketType? ticketTypeFilter, String? staffIdFilter, bool clearSearch = false, bool clearDate = false, bool clearStatus = false, }) { emit( state.copyWith( searchTerm: searchTerm, dateRange: dateRange, statusFilter: statusFilter, ticketTypeFilter: ticketTypeFilter, staffIdFilter: staffIdFilter, clearSearch: clearSearch, clearDate: clearDate, clearStatus: clearStatus, ), ); loadTickets(refresh: true); // Applica i filtri e ricarica } void toggleTicketSelection(TicketModel ticket) { final currentSelection = Set.from(state.selectedTickets); if (currentSelection.contains(ticket)) { currentSelection.remove(ticket); } else { currentSelection.add(ticket); } emit(state.copyWith(selectedTickets: currentSelection)); } void clearSelection() { emit(state.copyWith(selectedTickets: {})); } void selectAll(List tickets) { emit(state.copyWith(selectedTickets: tickets.toSet())); } Future closeTicketsBulk({ required List ticketIds, Map? loanReturns, }) async { // 1. Escludiamo i ticket per cui NON è stato restituito il muletto if (loanReturns != null) { for (final map in loanReturns.entries) { if (!map.value) { ticketIds.remove(map.key); } } } // Se non c'è più nulla da chiudere (es. ha rifiutato tutto), usciamo if (ticketIds.isEmpty) { clearSelection(); return; } // 2. Prepariamo i ticket per il DB final List ticketsToUpdate = []; for (final ticketId in ticketIds) { final ticket = state.tickets .firstWhere((ticket) => ticket.id == ticketId) .copyWith(ticketStatus: TicketStatus.closed); ticketsToUpdate.add(ticket); } // 3. Salviamo su DB (in background) for (final ticket in ticketsToUpdate) { await _repository.updateTicket(ticket); await _trackingRepository.logQuickEvent( companyId: ticket.companyId, message: 'Ticket chiuso - Riconsegnato', type: TrackingType.statusChange, parentId: ticket.id!, parentType: TrackingParentType.ticket, ); } // 4. LA MAGIA: AGGIORNAMENTO LOCALE ISTANTANEO final updatedTickets = state.tickets.map((t) { if (ticketIds.contains(t.id)) { return t.copyWith(ticketStatus: TicketStatus.closed); } return t; }).toList(); // 5. Emettiamo il nuovo stato aggiornato e puliamo la selezione in un colpo solo emit( state.copyWith( tickets: updatedTickets, selectedTickets: {}, // Equivalente di clearSelection() ), ); // Opzionale: Se vuoi comunque riallinearti al server in modo silenzioso dopo l'animazione // loadTickets(refresh: true); } }