import 'package:hl_lieferservice/dto/payment.dart';

import 'car.dart';
import 'delivery.dart';

class Payment {
  const Payment({
    required this.description,
    required this.shortcode,
    required this.id,
  });

  final String id;
  final String description;
  final String shortcode;

  factory Payment.fromDTO(PaymentMethodDTO dto) {
    return Payment(
      description: dto.description,
      shortcode: dto.shortCode,
      id: dto.id,
    );
  }

  Payment copyWith({
    String? description,
    String? shortcode,
    String? id,
  }) {
    return Payment(
      description: description ?? this.description,
      shortcode: shortcode ?? this.shortcode,
      id: id ?? this.id,
    );
  }
}

class Tour {
  Tour({
    required this.date,
    required this.deliveries,
    required this.driver,
    required this.discountArticleNumber,
    required this.paymentMethods,
  }) : deliveriesPerCar = {};

  final DateTime date;
  final String discountArticleNumber;
  Driver driver;
  final List<Delivery> deliveries;
  List<Payment> paymentMethods;

  Map<String, List<Delivery>> deliveriesPerCar;

  int getFinishedDeliveries(int carId) {
    return deliveries
        .where((delivery) => delivery.carId == carId)
        .where((delivery) => delivery.state == DeliveryState.finished)
        .toList()
        .length;
  }

  /// Returns true if the car still has loaded articles assigned to a delivery
  /// that has not been finished yet. Scannable articles count when their
  /// effective scanned amount (scanned minus removed) is positive; non-scannable
  /// articles count when their target amount is greater than zero.
  bool hasUndeliveredLoadedArticles(int carId) {
    return deliveries.any((delivery) {
      if (delivery.carId != carId) return false;
      if (delivery.state == DeliveryState.finished) return false;
      return delivery.articles.any((article) {
        if (article.scannable) {
          return article.scannedAmount > article.scannedRemovedAmount;
        }
        return article.amount > 0;
      });
    });
  }

  Tour copyWith({
    DateTime? date,
    String? discountArticleNumber,
    Driver? driver,
    List<Delivery>? deliveries,
    List<Payment>? paymentMethods,
  }) {
    return Tour(
      date: date ?? this.date.copyWith(),
      discountArticleNumber:
          discountArticleNumber ?? this.discountArticleNumber,
      driver: driver ?? this.driver,
      deliveries: deliveries ?? this.deliveries,
      paymentMethods: paymentMethods ?? this.paymentMethods,
    );
  }
}

class Driver {
  Driver({
    required this.teamNumber,
    required this.name,
    required this.salutation,
    required this.cars,
  });

  final int teamNumber;
  final String name;
  final String salutation;
  List<Car> cars;

  /// If the driver is representing a company, then the company name is returned.
  String getSalutatedLastName() {
    if (salutation != "Firma") {
      return "$salutation, ${name.split(" ").first}";
    }

    return "$salutation, $name";
  }

  Driver copyWith(
    int? teamNumber,
    String? name,
    String? salutation,
    List<Car>? cars,
  ) {
    return Driver(
      teamNumber: teamNumber ?? this.teamNumber,
      name: name ?? this.name,
      salutation: salutation ?? this.salutation,
      cars: cars ?? this.cars,
    );
  }
}
