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<TicketListState> {
  final TicketRepository _repository = GetIt.I.get<TicketRepository>();
  final TrackingRepository _trackingRepository = GetIt.I
      .get<TrackingRepository>();
  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<void> 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<TicketModel>.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<TicketModel> tickets) {
    emit(state.copyWith(selectedTickets: tickets.toSet()));
  }

  Future<void> closeTicketsBulk({
    required List<String> ticketIds,
    Map<String, bool>? 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<TicketModel> 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);
  }

  Future<void> deleteTickets(List<TicketModel> tickets) async {
    try {
      for (final ticket in tickets) {
        await _repository.deleteTicket(ticket.id!);
      }
      // Rimuoviamo i ticket localmente senza ricaricare tutto
      final remainingTickets = state.tickets
          .where((t) => !tickets.any((toDelete) => toDelete.id == t.id))
          .toList();
      emit(state.copyWith(tickets: remainingTickets, selectedTickets: {}));
    } catch (e) {
      emit(state.copyWith(errorMessage: e.toString()));
    }
  }
}
