import 'package:comwell_key_app/check_out/models/payment_method.dart';
import 'package:comwell_key_app/services/models/booking_dto.dart';
import 'package:comwell_key_app/check_out/pages/check_out_page.dart';
import 'package:equatable/equatable.dart';

class CheckoutState extends Equatable {
  final Iterable<BookingAddonItem> _items;
  final bool isTermsAccepted;
  final bool applyClubPoints;
  final int clubPoints;
  final bool successfulCheckout;
  final CheckoutPage page;
  final CheckoutPaymentMethod? paymentMethod;
  final bool showTermsError;
  final num bookingBalance;
  final bool isPaymentProcessingNeeded;
  final bool isLoading;
  final bool hasCheckoutError;

  int get totalPriceBeforeDiscount => _sumOfList(_items);

  int get totalPriceAfterDiscount => _sumOfList(items);

  int get totalPrice => _sumOfList(_items);

  Iterable<BookingAddonItem> get items {
    if (applyClubPoints) {
      return [
        ..._items,
        BookingAddonItem("discount", "discount", clubPoints * -1, clubPoints * -1),
      ];
    }

    return _items;
  }

  int _sumOfList(Iterable<BookingAddonItem> list) {
    if (list.isEmpty) return 0;
    return list.map((item) => item.price).reduce((total, price) => total + price);
  }

  const CheckoutState({
    required Iterable<BookingAddonItem> items,
    required this.isTermsAccepted,
    required this.page,
    required this.showTermsError,
    required this.clubPoints,
    required this.applyClubPoints,
    this.paymentMethod,
    required this.bookingBalance,
    required this.successfulCheckout,
    required this.isPaymentProcessingNeeded,
    required this.isLoading,
    required this.hasCheckoutError,
  }) : _items = items;

  CheckoutState.initial(this.bookingBalance)
    : _items = [],
      isTermsAccepted = false,
      page = CheckoutPage.confirmation,
      showTermsError = false,
      clubPoints = 0,
      paymentMethod = CheckoutPaymentMethod.creditCard,
      applyClubPoints = false,
      successfulCheckout = false,
      isLoading = false,
      isPaymentProcessingNeeded = true,
      hasCheckoutError = false;

  CheckoutState itemsUpdated(Iterable<BookingAddonItem> items) {
    final newItems = <BookingAddonItem>[];
    for (var item in items) {
      newItems.add(item.copyWith(price: item.price * item.quantity));
    }
    return _copyWith(items: newItems);
  }

  CheckoutState loading() => _copyWith(isLoading: true);

  CheckoutState loaded() => _copyWith(isLoading: false);

  CheckoutState termsAccepted() => _copyWith(termsAccepted: true, showTermsError: false);

  CheckoutState termsDenied() => _copyWith(termsAccepted: false);

  CheckoutState clubPointsApplied() => _copyWith(applyClubPoints: true);

  CheckoutState clubPointsRemoved() => _copyWith(applyClubPoints: false);

  CheckoutState paymentMethodChanged(CheckoutPaymentMethod payment) =>
      _copyWith(paymentMethod: payment);

  CheckoutState pageChanged(CheckoutPage page) => _copyWith(page: page);

  CheckoutState clubPointsFetched(int clubPoints) => _copyWith(clubPoints: clubPoints);

  CheckoutState showAcceptTermsError() => _copyWith(showTermsError: true);

  CheckoutState checkoutSuccess() => _copyWith(successfulCheckout: true, hasCheckoutError: false);

  CheckoutState checkoutError() => _copyWith(successfulCheckout: false, hasCheckoutError: true);

  CheckoutState paymentProcessingNeeded() => _copyWith(isPaymentProcessingNeeded: true);

  CheckoutState paymentProcessingNotNeeded() => _copyWith(isPaymentProcessingNeeded: false);

  CheckoutState _copyWith({
    Iterable<BookingAddonItem>? items,
    bool? termsAccepted,
    bool? applyClubPoints,
    CheckoutPage? page,
    CheckoutPaymentMethod? paymentMethod,
    int? clubPoints,
    bool? showTermsError,
    num? bookingBalance,
    bool? successfulCheckout,
    bool? isPaymentProcessingNeeded,
    bool? isLoading,
    bool? hasCheckoutError,
  }) {
    return CheckoutState(
      items: items ?? _items,
      page: page ?? this.page,
      clubPoints: clubPoints ?? this.clubPoints,
      showTermsError: showTermsError ?? this.showTermsError,
      isTermsAccepted: termsAccepted ?? isTermsAccepted,
      applyClubPoints: applyClubPoints ?? this.applyClubPoints,
      paymentMethod: paymentMethod ?? this.paymentMethod,
      bookingBalance: bookingBalance ?? this.bookingBalance,
      successfulCheckout: successfulCheckout ?? this.successfulCheckout,
      isPaymentProcessingNeeded: isPaymentProcessingNeeded ?? this.isPaymentProcessingNeeded,
      isLoading: isLoading ?? this.isLoading,
      hasCheckoutError: hasCheckoutError ?? this.hasCheckoutError,
    );
  }

  @override
  List<Object?> get props => [
    _items,
    isTermsAccepted,
    applyClubPoints,
    page,
    showTermsError,
    paymentMethod,
    totalPriceBeforeDiscount,
    totalPriceAfterDiscount,
    totalPrice,
    successfulCheckout,
    isPaymentProcessingNeeded,
    isLoading,
    hasCheckoutError,
  ];
}