import 'package:comwell_key_app/overview/models/guest.dart';
import 'package:comwell_key_app/overview/models/payment_details.dart';
import 'package:comwell_key_app/services/models/booking_dto.dart';
import 'package:equatable/equatable.dart';

class Booking extends Equatable {
  final String id;
  final String confirmationNumber;
  final String roomNumber;
  final DateTime startDate;
  final DateTime endDate;
  final ReservationStatus reservationStatus;
  final String image;
  final String hotelName;
  final String hotelCode;
  final String firstName;
  final String lastName;
  final String bookerFirstName;
  final String bookerLastName;
  final String roomType;
  final int adults;
  final int children;
  final DateTime bookingDate;
  final bool digitalCard;
  final List<Guest> guests;
  final num? balance;
  final bool isPrimaryGuest;
  final String? maskedCardNumber;
  final List<BookingAddonItem>? addOnItems;

  Booking({
    required this.id,
    required this.confirmationNumber,
    required this.roomNumber,
    required this.startDate,
    required this.endDate,
    required this.reservationStatus,
    required this.image,
    required this.hotelName,
    required this.firstName,
    required this.lastName,
    required this.bookerFirstName,
    required this.bookerLastName,
    required this.roomType,
    required this.children,
    required this.adults,
    required this.hotelCode,
    required this.bookingDate,
    required this.digitalCard,
    required this.balance,
    required this.isPrimaryGuest,
    required this.maskedCardNumber,
    List<Guest>? guests,
    required this.addOnItems,
  }) : guests = guests ?? [];

  @override
  String toString() {
    return "Booking(id: $id, ConfirmationNumber: $confirmationNumber, roomNumber: $roomNumber, startDate: $startDate, endDate: $endDate, reservationStatus: $reservationStatus, image: $image, hotelName: $hotelName, hotelCode: $hotelCode, roomType: $roomType, adults: $adults, children: $children, bookingDate: $bookingDate, digitalCard: $digitalCard, guests: $guests, addOnItems: $addOnItems, isPrimaryGuest: $isPrimaryGuest, totalCharge: $balance, maskedCardNumber: $maskedCardNumber)";
  }

  List<String> get addOnItemCodes => addOnItems?.map((e) => e.code).toList() ?? [];
  List<String> get addOnItemDescriptions => addOnItems?.map((e) => e.description).toList() ?? [];
  int get addOnItemPrice => addOnItems?.map((e) => e.price).reduce((total, price) => total + price) ?? 0;

  @override
  List<Object?> get props => [
    id,
    roomNumber,
    startDate,
    endDate,
    image,
    hotelName,
    roomType,
    children,
    adults,
    hotelCode,
    bookingDate,
    guests,
    balance,
    isPrimaryGuest,
    maskedCardNumber,
    reservationStatus,
    addOnItems,
  ];

  Booking copyWith({
    String? id,
    String? userId,
    String? roomNumber,
    DateTime? startDate,
    DateTime? endDate,
    ReservationStatus? reservationStatus,
    String? image,
    String? hotelName,
    String? hotelCode,
    String? roomType,
    int? adults,
    int? children,
    String? primaryGuestFirstName,
    String? primaryGuestLastName,
    String? bookerFirstName,
    String? bookerLastName,
    bool? isPrimaryGuest,
    DateTime? bookingDate,
    PaymentDetails? paymentDetails,
    String? confirmationNumber,
    List<Guest>? guests,
    num? totalCharge,
    List<BookingAddonItem>? addOnItems,
  }) {
    return Booking(
      id: id ?? this.id,
      roomNumber: roomNumber ?? this.roomNumber,
      startDate: startDate ?? this.startDate,
      endDate: endDate ?? this.endDate,
      reservationStatus: reservationStatus ?? this.reservationStatus,
      image: image ?? this.image,
      hotelName: hotelName ?? this.hotelName,
      hotelCode: hotelCode ?? this.hotelCode,
      firstName: firstName,
      lastName: lastName,
      bookerFirstName: bookerFirstName ?? this.bookerFirstName,
      bookerLastName: bookerLastName ?? this.bookerLastName,
      roomType: roomType ?? this.roomType,
      adults: adults ?? this.adults,
      children: children ?? this.children,
      bookingDate: bookingDate ?? this.bookingDate,
      confirmationNumber: confirmationNumber ?? this.confirmationNumber,
      digitalCard: digitalCard,
      guests: guests ?? this.guests,
      balance: totalCharge ?? balance,
      isPrimaryGuest: isPrimaryGuest ?? this.isPrimaryGuest,
      maskedCardNumber: maskedCardNumber,
      addOnItems: addOnItems ?? this.addOnItems,
    );
  }

  Booking updateGuests(List<String> guestNames) {
    final updatedGuests = guests
        .where(
          (guest) => !guestNames.contains(guest.firstName) && !guestNames.contains(guest.lastName),
        )
        .toList();

    return copyWith(guests: updatedGuests);
  }
}

enum ReservationStatus {
  checkedin,
  checkedout,
  cancelled,
  noshow,
  newreservation,
  preregistered,
  preregistrationfinalized,
  unknown;

  static ReservationStatus fromString(String value) {
    if (value.toLowerCase() == 'new') {
      return ReservationStatus.newreservation;
    }
    final status = ReservationStatus.values.firstWhere(
      (status) => status.name.toLowerCase() == value.toLowerCase(),
    );
    return status;
  }
}