import 'package:comwell_key_app/overview/models/booking.dart';
import 'package:comwell_key_app/presentation/base/base_cubit.dart';
import 'package:comwell_key_app/up_sales/cubit/up_sales_state.dart';
import 'package:comwell_key_app/up_sales/models/addon_list.dart';
import 'package:comwell_key_app/up_sales/models/addon_upgrade.dart';
import 'package:comwell_key_app/up_sales/models/room_upgrade.dart';
import 'package:comwell_key_app/up_sales/models/up_sales_processing_state.dart';
import 'package:comwell_key_app/up_sales/models/upgrade.dart';
import 'package:comwell_key_app/up_sales/models/up_sales.dart';
import 'package:comwell_key_app/up_sales/up_sales_repository.dart';

class UpSalesCubit extends BaseCubit<UpSalesState> {
  final UpSalesRepository upSaleRepository;
  late UpSales upSales;
  final Booking booking;

  UpSalesCubit({required this.upSaleRepository, required this.booking})
    : super(UpSalesState.initial()) {
    init();
  }

  void init() async {
    safeEmit(state.loading());
    upSales = await upSaleRepository.getRemoteUpSales(
      booking.confirmationNumber,
      booking.hotelCode,
    );

    safeEmit(
      UpSalesState(
        selected: false,
        addOnUpgrades: upSales.addOnUpgrades,
        availableRoomUpgrades: upSales.roomUpgrades,
        selectedRoomUpgrade: '',
        isLoading: false,
        processingState: UpSalesProcessingStateNotStarted(),
        error: null,
      ),
    );
    try {
      safeEmit(state.loaded(upSales: upSales));
    } catch (e, st) {
      logError(e, st);
      safeEmit(state.setupError(error: Exception(e)));
    }
  }

  void onContinue() {
    safeEmit(state.copyWith(selected: false));
  }

  void updateAddonUpgradeQuantity(AddOnUpgrade upgrade, int quantity) {
    safeEmit(state.updateSelectedUpgradeWithQuantity(upgrade, quantity));
  }

  void toggleSelectedUpgrade(Upgrade upgrade) {
    if (upgrade is RoomUpgrade) {
      safeEmit(state.toggleRoomUpgrade(roomUpgrade: upgrade));
    } else if (upgrade is AddOnUpgrade) {
      safeEmit(state.toggleSelectedAddonUpsale(upgrade: upgrade));
    }
  }

  int get extrasTotalPrice {
    //This is the total price of the selected up sales and the price of the selected
    //room upgrade if it is selected

    return selectedAddOnUpgrades.fold(0, (sum, upgrade) => sum + upgrade.price * upgrade.quantity) +
        (state.selectedRoomUpgrade.isNotEmpty
            ? upSales.roomUpgrades.firstWhere((e) => e.id == state.selectedRoomUpgrade).price
            : 0);
  }

  List<AddOnUpgrade> get selectedAddOnUpgrades {
    final selectedUpgrades = state.addOnUpgrades.where((upgrade) => upgrade.isAddedToCart).toList();
    return selectedUpgrades;
  }

  List<AddOnUpgrade> get otherUpgrades {
    final selectedUpgrades = state.addOnUpgrades.where((upgrade) => !upgrade.isService).toList();
    return selectedUpgrades;
  }

  void toggleTermsAccepted() {
    safeEmit(state.copyWith(termsAccepted: !state.termsAccepted));
  }

  Future<void> addUpSalesToBooking() async {
    safeEmit(state.processingStateUpdated(UpSalesProcessingStateProcessing()));
    try {
      // Extract RoomUpgrade from selectedUpSales to get the roomType
      final roomType = state.selectedRoomUpgrade;

      // Convert selected up sales to AddOnList objects using their individual quantities
      final List<AddOnList> addonList = state.addOnUpgrades
          .where((upgrade) => upgrade.quantity > 0)
          .map((upgrade) => AddOnList(itemCode: upgrade.id, quantity: upgrade.quantity))
          .toList();

      await upSaleRepository.addUpSalesToBooking(
        booking.confirmationNumber,
        booking.hotelCode,
        roomType,
        addonList,
      );
      await Future<void>.delayed(const Duration(seconds: 2));
      safeEmit(state.processingStateUpdated(UpSalesProcessingStateSuccess()));
    } catch (e, st) {
      logError(e, st);
      safeEmit(state.processingStateUpdated(UpSalesProcessingStateError()));
    }
  }
}