import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:loader_overlay/src/overlay_controller_widget_extension.dart';

import './widgets/payment_web_view.dart';
import '../../app.dart';
import 'state.dart';

class CartController extends GetxController {
  final state = new CartState();

  LoginStatusController loginStatusController = Get.put(LoginStatusController());

  @override
  void onInit() {
    get();
    super.onInit();
  }

  @override
  void dispose() {
    state.couponCodeCtrl.dispose();
    super.dispose();
  }

  Future<void> get() async {
    if (!loginStatusController.loginStatus) return;

    state.isLoading.value = true;
    state.cartModel.value = await ShoppingCartApi.get();

    if (state.cartModel.value != null) {
      state.couponCodeCtrl.text = state.cartModel.value!.couponCode ?? '';
    }

    state.isLoading.value = false;
  }

  Future<void> add(BuildContext context, Map<String, dynamic> params, int productId) async {
    context.loaderOverlay.show();
    state.cartModel.value = await ShoppingCartApi.add(context, params, productId);
    context.loaderOverlay.hide();
  }

  Future<void> onIncDecTapped(BuildContext context, int itemId, int newQuantity) async {
    debugPrint('onIncDecTapped');

    if (newQuantity < 1) {
      showSnack('warning'.tr, 'min_item'.tr, SnackType.WARNING);
      return;
    }

    context.loaderOverlay.show();
    final response = await ShoppingCartApi.update(itemId, newQuantity);
    if (response != null) {
      state.cartModel.value = response;
    }
    context.loaderOverlay.hide();
  }

  Future<void> onTrashTapped(BuildContext context, int itemId) async {
    debugPrint('onTrashTapped $itemId');

    context.loaderOverlay.show();
    state.cartModel.value = await ShoppingCartApi.remove(itemId);
    context.loaderOverlay.hide();
  }

  Future<void> onWishlistTapped(BuildContext context, int productId) async {
    debugPrint('onWishlistTapped $productId');

    context.loaderOverlay.show();
    final result = await WishlistApi.addRemove(productId);

    if (result) {
      state.cartModel.value = await ShoppingCartApi.get();
    }

    context.loaderOverlay.hide();
  }

  Future<void> onCheckoutTapped() async {
    debugPrint('onCheckoutTapped');
    Get.toNamed(AppRoutes.CHECKOUT);
  }

  Future<void> saveOrder(BuildContext context) async {
    context.loaderOverlay.show();

    final Map<String, dynamic> params = {
      'shipping_method': state.selectedShippingRate.value?.method ?? '',
      'payment': state.selectedPaymentMethod.value?.method,
      'locale': await getLocale(),
    };

    final response = await OrderApi.saveOrder(params);

    final url = response['url'];
    if (response['success']) {
      if (url.isEmpty) {
        clearCartAndNavigateToOrderList();
      } else {
        debugPrint('is not empty');
        Get.to(() => PaymentWebView(url: url));
      }
    }

    context.loaderOverlay.hide();
  }

  Future<void> applyCoupon(BuildContext context) async {
    if (state.couponCodeCtrl.value.text.isEmpty) {
      showSnack('warning'.tr, 'enter_coupon_code'.tr, SnackType.WARNING);
      return;
    }

    context.loaderOverlay.show();
    final CartModel? result = await ShoppingCartApi.applyCoupon(state.couponCodeCtrl.text);

    if (result != null) {
      state.isCouponApplied.value = true;
      state.cartModel.value = result;
    }

    context.loaderOverlay.hide();
  }

  Future<void> deleteCoupon(BuildContext context) async {
    if (state.couponCodeCtrl.value.text.isEmpty) {
      showSnack('warning'.tr, 'enter_coupon_code'.tr, SnackType.WARNING);
      return;
    }

    context.loaderOverlay.show();
    final CartModel? result = await ShoppingCartApi.deleteCoupon();

    if (result != null) {
      state.isCouponApplied.value = false;
      state.cartModel.value = result;
      state.couponCodeCtrl.text = '';
    }

    context.loaderOverlay.hide();
  }

  Future<void> onAddressSelected(BuildContext context, AddressModel address) async {
    debugPrint('onAddressSelected ${address.id}');
    AddressController ac = Get.put(AddressController());
    debugPrint('AddressController ${ac.addresses.length}');

    context.loaderOverlay.show();

    // get current user. TODO: save to shared preferences
    final UserModel? userModel = await AuthApi.getCurrentUser();

    if (userModel == null) {
      context.loaderOverlay.hide();
      showSnack('warning'.tr, 'please_login'.tr, SnackType.WARNING);
      return;
    }

    final Map<String, dynamic> params = {
      'billing': {
        'address1': {
          '0': '${address.address1.first} , ${address.city}',
        },
        'use_for_shipping': true,
        'first_name': '${userModel.firstName}',
        'last_name': '${userModel.lastName}',
        // 'email': '${userModel.email}',
        'address_id': address.id,
      },
      'shipping': {
        'address1': {
          '0': '${address.address1.first} , ${address.city}',
        },
        'first_name': '${userModel.firstName}',
        'last_name': '${userModel.lastName}',
        // 'email': 'john@gmail.com',
        'address_id': address.id,
      }
    };

    final response = await OrderApi.saveAddress(params);

    context.loaderOverlay.hide();

    if (response == null) {
      showSnack('error'.tr, 'error_occurred'.tr, SnackType.ERROR);
      return;
    }

    clearLists();

    state.shippingRates.addAll(response['shipping_rates']);
    state.paymentMethods.addAll(response['payment_methods']);

    // set selected shipping rate
    final savedShippingMethod = state.cartModel.value?.shippingRate?.method;
    final shippingRate = state.shippingRates.firstWhereOrNull((sr) => sr.method == savedShippingMethod);
    state.selectedShippingRate.value = shippingRate;

    // set selected payment method
    final savedPaymentMethod = state.cartModel.value?.paymentMethod;
    final paymentMethod = state.paymentMethods.firstWhereOrNull((pm) => pm.method == savedPaymentMethod);
    state.selectedPaymentMethod.value = paymentMethod;

    final AddressModel? defaultAddress = ac.addresses.firstWhereOrNull((a) => a.isDefault);

    if (defaultAddress != null) {
      defaultAddress.isDefault = false;
      ac.addresses[ac.addresses.indexWhere((a) => a.id == defaultAddress.id)] = defaultAddress;
    }

    address.isDefault = true;
    ac.addresses[ac.addresses.indexWhere((a) => a.id == address.id)] = address;

    ac.refresh();
  }

  void onOrderNowTapped() {
    debugPrint('onOrderNowTapped 1');
    Get.offNamed(AppRoutes.CART_ORDER);
  }

  void clearLists() {
    state.shippingRates.clear();
    state.paymentMethods.clear();
  }

  Future<void> onShippingRateChange(ShippingRateModel? model, BuildContext context) async {
    debugPrint('onShippingRateChange ${model?.price}');

    state.selectedShippingRate.value = model;

    context.loaderOverlay.show();

    final result = await OrderApi.saveShipping({'shipping_method': model?.method});

    if (result != null) {
      state.cartModel.value = result;
      debugPrint('onShippingRateChange');
    }

    context.loaderOverlay.hide();
  }

  void onPaymentMethodChange(PaymentMethodModel? model) {
    debugPrint('onPaymentMethodChange ${model?.method}');

    state.selectedPaymentMethod.value = model;
  }

  void navigateToLogin() => navigateToLoginScreen();

  void onProductCartTapped() {
    debugPrint('onProductCartTapped');
    // final Map<String, dynamic> arguments = {
    // 'productModel': widget.model,
    // };
    // Get.toNamed(AppRoutes.PRODUCT_DETAIL, arguments: arguments);
    // Get.to(() => ProductDetailsPage(model: widget.model));
  }

  void onBackTapped() {
    clearLists();
    Get.back();
  }

  void clearCartAndNavigateToOrderList() {
    debugPrint('clearCartAndNavigateToOrderList');
    //clear cart item
    state.cartModel.value = null;

    // navigate to orders
    Get.offNamedUntil('/', (route) => false);
    Get.toNamed(AppRoutes.ORDERS);
  }
}


  /* 
  

  // Methods for saving products in SharedPreferences

  RxList<CartModel> cartList = <CartModel>[].obs;

  Future<void> saveCartToSharedPrefs() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();

    await prefs.remove(Constants.CART_LIST);

    if (cartList.length > 0) {
      final cartListString = jsonEncode(cartList);
      prefs.setString(Constants.CART_LIST, cartListString);
    }
  }

  Future<void> getCartFromSharedPrefs() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();

    final cartListString = prefs.getString(Constants.CART_LIST);

    if (cartListString != null) {
      final List<dynamic> list = jsonDecode(cartListString);

      cartList.clear();
      for (int i = 0; i < list.length; i++) {
        final CartModel cartModel = CartModel.fromJson(list[i]);
        cartList.add(cartModel);
      }
    }

      bool itemExistsInCart(int vendorId, int productId) {
    final CartModel? cart = cartList.firstWhereOrNull((c) => c.vendor!.id == vendorId);

    if (cart == null) return false;

    final ProductCartModel? product = cart.products.firstWhereOrNull((p) => p.product.id == productId);

    return product != null;
  }

  } */