import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flux/core/blocs/session/session_cubit.dart';
import 'package:flux/features/tickets/data/tickets_shipping_repository.dart';
import 'package:flux/features/tickets/models/shipping_document_model.dart';
import 'package:flux/features/master_data/providers/models/provider_location_model.dart';
import 'package:flux/features/master_data/providers/models/provider_model.dart';
import 'package:flux/features/settings/document_sequence/data/document_sequence_repository.dart';
import 'package:flux/features/settings/document_sequence/models/document_sequence_model.dart';
import 'package:flux/features/tickets/models/ticket_model.dart';
import 'package:flux/features/tickets/utils/ticket_shipping_pdf_service.dart';
import 'package:get_it/get_it.dart';
import 'package:printing/printing.dart';

part 'ticket_shipping_state.dart';

class TicketShippingCubit extends Cubit<TicketShippingState> {
  final TicketsShippingRepository _repository =
      GetIt.I<TicketsShippingRepository>();
  final DocumentSequenceRepository _sequenceRepository =
      GetIt.I<DocumentSequenceRepository>();
  TicketShippingCubit({required List<TicketModel> tickets})
    : super(
        TicketShippingState(
          // Inizializziamo il modello direttamente nello stato!
          document: ShippingDocumentModel(
            companyId: GetIt.I.get<SessionCubit>().state.company!.id!,
            ticketIds: tickets.map((t) => t.id!).toList(),
            providerId: '', // Sarà riempito alla selezione
            destinationLocationId: '', // Sarà riempito alla selezione
            docNumber: '',
            docDate: DateTime.now(),
          ),
          tickets: tickets,
        ),
      );

  Future<void> loadRepairCenters() async {
    emit(state.copyWith(status: TicketShippingStatus.loading));
    try {
      final repairCenters = await _repository.fetchRepairCenters();
      emit(
        state.copyWith(
          status: TicketShippingStatus.initial,
          availableProviders: repairCenters,
        ),
      );
    } catch (e) {
      emit(
        state.copyWith(
          status: TicketShippingStatus.failure,
          errorMessage: e.toString(),
        ),
      );
    }
  }

  void selectProvider(String providerId) {
    final ProviderModel provider = state.availableProviders.firstWhere(
      (p) => p.id == providerId,
    );
    final locations = provider.locations ?? [];

    String destinationId = '';
    if (locations.length == 1) {
      destinationId = locations.first.id ?? '';
    } else if (locations.any((l) => l.isMain)) {
      destinationId = locations.firstWhere((l) => l.isMain).id ?? '';
    }

    emit(
      state.copyWith(
        availableLocations: locations,
        document: state.document.copyWith(
          providerId: providerId,
          destinationLocationId: destinationId,
        ),
      ),
    );
  }

  void selectLocation(String locationId) {
    emit(
      state.copyWith(
        document: state.document.copyWith(destinationLocationId: locationId),
      ),
    );
  }

  Future<void> toggleAutoNumber(bool value) async {
    // Aggiorniamo subito l'UI per mostrare che lo switch si è acceso
    emit(state.copyWith(isAutoNumber: value));
  }

  // Metodo unico e pulito per aggiornare i campi testuali/numerici del documento
  void updateDocument({
    String? docNumber,
    DateTime? docDate,
    int? packageCount,
    double? weight,
    String? shippingReason,
    String? notes,
  }) {
    emit(
      state.copyWith(
        document: state.document.copyWith(
          docNumber: docNumber,
          docDate: docDate,
          packageCount: packageCount,
          weight: weight,
          shippingReason: shippingReason,
          notes: notes,
        ),
      ),
    );
  }

  Future<void> confirmShipment({required TicketStatus newTicketStatus}) async {
    if (state.document.providerId.isEmpty ||
        state.document.destinationLocationId.isEmpty) {
      emit(
        state.copyWith(
          status: TicketShippingStatus.failure,
          errorMessage: 'Seleziona laboratorio e sede.',
        ),
      );
      return;
    }
    if (!state.isAutoNumber && state.document.docNumber.trim().isEmpty) {
      emit(
        state.copyWith(
          status: TicketShippingStatus.failure,
          errorMessage: 'Inserisci il numero DDT.',
        ),
      );
      return;
    }

    emit(state.copyWith(status: TicketShippingStatus.loading));
    if (state.isAutoNumber) {
      try {
        final nextNumber = await _sequenceRepository.getNextDocumentNumber(
          DocumentType.ticketsShipping.name,
        );
        updateDocument(docNumber: nextNumber);
        // 3. GENERIAMO I BYTES DEL PDF
        final provider = state.availableProviders.firstWhere(
          (p) => p.id == state.document.providerId,
        );
        final location = state.availableLocations.firstWhere(
          (l) => l.id == state.document.destinationLocationId,
        );
        final pdfBytes = await TicketShippingPdfService.generateDdt(
          company: GetIt.I.get<SessionCubit>().state.company!,
          provider: provider,
          location: location,
          document: state.document,
          tickets: state.tickets,
        );
        await _repository.createShipmentWithPdf(
          document: state.document,
          pdfBytes: pdfBytes,
          newTicketStatus: newTicketStatus,
        );
        await Printing.layoutPdf(
          onLayout: (format) async => pdfBytes,
          name: 'DDT_${state.document.docNumber}.pdf',
        );
        emit(state.copyWith(status: TicketShippingStatus.success));
      } catch (e) {
        emit(state.copyWith(isAutoNumber: false, errorMessage: e.toString()));
        return;
      }
    }
  }
}
