import 'dart:typed_data';

import 'package:hl_lieferservice/model/car.dart';
import 'package:hl_lieferservice/model/tour.dart';

import '../../../../model/delivery.dart';

abstract class TourEvent {}

class LoadTour extends TourEvent {
  String teamId;

  LoadTour({required this.teamId});
}

class RequestDeliveryDistanceEvent extends TourEvent {
  Tour tour;

  RequestDeliveryDistanceEvent({required this.tour});
}

class RequestSortingInformationEvent extends TourEvent {
  Tour tour;
  List<Payment> payments;

  RequestSortingInformationEvent({
    required this.tour,
    required this.payments,
  });
}

class ReorderDeliveryEvent extends TourEvent {
  int newPosition;
  int oldPosition;
  String carId;

  ReorderDeliveryEvent({required this.newPosition, required this.oldPosition, required this.carId});
}

/// Ersetzt die komplette Sortier-Information (z. B. beim Zurücksetzen auf
/// die Default-Reihenfolge in der Sortier-Page). Persistiert lokal über
/// den ReorderService, kein Backend-Call.
class ReplaceSortingEvent extends TourEvent {
  final String carId;
  final Map<String, List<String>> newSortingInformation;

  ReplaceSortingEvent({
    required this.carId,
    required this.newSortingInformation,
  });
}

/// Bestätigung der Sortierung durch den Fahrer. Löst den (aktuell ge-
/// stubbten) Backend-Call zur Persistierung der Reihenfolge aus und
/// schaltet bei Erfolg in Phase [DeliveryPhase.beladen].
class ConfirmSortingEvent extends TourEvent {
  final String carId;

  ConfirmSortingEvent({required this.carId});
}

/// Stellt sicher, dass der Sortier-Bucket für [carId] alle aktuell in der
/// Tour vorhandenen Lieferungen enthält — und zwar UNABHÄNGIG von
/// `delivery.carId`. Hintergrund: zum Sortier-Zeitpunkt sind die Lieferungen
/// dem Fahrzeug oft noch nicht zugeordnet (das passiert erst beim Scannen
/// während des Beladens). Der Fahrer hat aber bereits sein Tagesfahrzeug
/// gewählt, also gehören alle Tour-Lieferungen in diesen Bucket. Bestehende
/// Reihenfolge bleibt erhalten, fehlende IDs werden hinten angehängt.
class EnsureSortingForCarEvent extends TourEvent {
  final String carId;

  EnsureSortingForCarEvent({required this.carId});
}

class TourUpdated extends TourEvent {
  Tour tour;
  List<Payment> payments;

  TourUpdated({required this.tour, required this.payments});
}

class PaymentOptionsUpdated extends TourEvent {
  List<Payment> options;

  PaymentOptionsUpdated({required this.options});
}

class UpdateTour extends TourEvent {
  Tour tour;

  UpdateTour({required this.tour});
}

class AssignCarEvent extends TourEvent {
  String deliveryId;
  String carId;

  AssignCarEvent({required this.deliveryId, required this.carId});
}

/// Hebt die Fahrzeug-Zuordnung einer Lieferung wieder auf. Wird im
/// Auswahl-Schritt ausgelöst, wenn der Fahrer eine eigene Lieferung
/// "freigibt", damit ein Kollege sie übernehmen kann. Aktuell ruft der
/// Handler nur den ProcessRepository-Stub auf — ein echtes Update der
/// Tour erfolgt erst mit dem realen Backend-Endpoint (siehe Repository).
class UnassignDeliveryEvent extends TourEvent {
  final String deliveryId;

  UnassignDeliveryEvent({required this.deliveryId});
}

class IncrementArticleScanAmount extends TourEvent {
  String internalArticleId;
  String deliveryId;
  String carId;

  IncrementArticleScanAmount({
    required this.internalArticleId,
    required this.deliveryId,
    required this.carId,
  });
}

class ScanArticleEvent extends TourEvent {
  ScanArticleEvent({
    required this.articleNumber,
    required this.carId,
    required this.deliveryId,
  });

  String articleNumber;
  String deliveryId;
  String carId;
}

/// Scan a single BOM component. The server call for the parent article is
/// deferred until *all* components are fully scanned.
class ScanComponentEvent extends TourEvent {
  ScanComponentEvent({
    required this.componentArticleNumber,
    required this.carId,
    required this.deliveryId,
  });

  String componentArticleNumber;
  String deliveryId;
  String carId;
}

class CancelDeliveryEvent extends TourEvent {
  String deliveryId;

  CancelDeliveryEvent({required this.deliveryId});
}

class HoldDeliveryEvent extends TourEvent {
  String deliveryId;

  HoldDeliveryEvent({required this.deliveryId});
}

class ReactivateDeliveryEvent extends TourEvent {
  String deliveryId;

  ReactivateDeliveryEvent({required this.deliveryId});
}

class LoadDeliveryEvent extends TourEvent {
  LoadDeliveryEvent({required this.delivery});

  Delivery delivery;
}

class UnscanArticleEvent extends TourEvent {
  UnscanArticleEvent({
    required this.articleId,
    required this.newAmount,
    required this.reason,
    required this.deliveryId,
  });

  String articleId;
  String deliveryId;
  String reason;
  int newAmount;
}

class ResetScanAmountEvent extends TourEvent {
  ResetScanAmountEvent({required this.articleId, required this.deliveryId});

  String articleId;
  String deliveryId;
}

class AddDiscountEvent extends TourEvent {
  AddDiscountEvent({
    required this.deliveryId,
    required this.value,
    required this.reason,
  });

  String deliveryId;
  String reason;
  int value;
}

class RemoveDiscountEvent extends TourEvent {
  RemoveDiscountEvent({required this.deliveryId});

  String deliveryId;
}

class UpdateDiscountEvent extends TourEvent {
  UpdateDiscountEvent({
    required this.deliveryId,
    required this.value,
    required this.reason,
  });

  String deliveryId;
  String? reason;
  int? value;
}

class CarsLoadedEvent extends TourEvent {
  List<Car> cars;

  CarsLoadedEvent({required this.cars});
}

class UpdateDeliveryOptionEvent extends TourEvent {
  UpdateDeliveryOptionEvent({
    required this.key,
    required this.value,
    required this.deliveryId,
  });

  String deliveryId;
  String key;
  dynamic value;
}

class UpdateSelectedPaymentMethodEvent extends TourEvent {
  UpdateSelectedPaymentMethodEvent({
    required this.payment,
    required this.deliveryId,
  });

  Payment payment;
  String deliveryId;
}

class FinishDeliveryEvent extends TourEvent {
  FinishDeliveryEvent({
    required this.deliveryId,
    required this.driverSignature,
    required this.customerSignature,
  });

  String deliveryId;
  Uint8List customerSignature;
  Uint8List driverSignature;
}

class SetArticleAmountEvent extends TourEvent {
  final String deliveryId;
  final String articleId;
  final String? reason;
  final int amount;

  SetArticleAmountEvent({
    required this.deliveryId,
    required this.articleId,
    required this.amount,
    this.reason,
  });
}