import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:loader_overlay/loader_overlay.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:snapping_sheet/snapping_sheet.dart';

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

class ProductController extends GetxController {
  final ProductModel model;

  ProductController(this.model);

  final state = new ProductState();

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

  // bottom sheet controller
  final snappingSheetController = SnappingSheetController();

  RxInt addingItemCount = 1.obs;
  RxDouble itemTotalPrice = 0.0.obs;

  @override
  void onInit() {
    debugPrint('Initial onInit');

    calculateItemTotalPrice();

    fetchConfigProducts(model);

    getProductAdditionalInfo();

    super.onInit();
  }

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

  Future<void> fetchConfigProducts(ProductModel model) async {
    debugPrint('fetchConfigProducts ${model.type}');
    if (model.type == 'configurable') {
      state.isLoading.value = true;

      Map<String, dynamic>? result = await ProductApi.getProductVariants(model.id);

      if (result == null) {
        // state.hasError.value = true;
        state.isLoading.value = false;
        return;
      }

      final level = result['level'];

      // has one step super attribute
      if (level == 1) {
        final SimpleAttributeModel attributeModel = SimpleAttributeModel.fromJson(result);
        debugPrint('simpleAttributeModel ${attributeModel.attribute.name}');
        state.simpleAttribute.value = attributeModel;
        state.selectedSimpleOption.value = attributeModel.options.first;
        state.selectedProduct.value = attributeModel.options.first.product;
        debugPrint('selectedProduct.value ${state.selectedProduct.value?.images}');
      }

      // has two step super attribute
      if (level == 2) {
        debugPrint('has two step super attribute ');
        final AttributeModel attributeModel = AttributeModel.fromJson(result);
        debugPrint('attributeModel ${attributeModel.attribute.name}');

        state.attribute.value = attributeModel;
        state.selectedOption.value = attributeModel.options.first;
        state.selectedProduct.value = attributeModel.options.first.variants.products?.first;
      }

      state.isLoading.value = false;
    }
  }

  Future<void> getProductAdditionalInfo() async {
    state.isAdditionalInfoLoading.value = true;
    state.hasAdditionalInfoError.value = false;

    final Map<String, dynamic> params = {
      'locale': await getLocale(),
      'currency': 'TMT',
    };

    final result = await ProductApi.getProductAdditionalInfo(model.id, params);

    if (result == null) {
      state.isAdditionalInfoLoading.value = false;
      state.hasAdditionalInfoError.value = true;
      return;
    }

    state.productAdditionalInfoList.addAll(result);

    state.isAdditionalInfoLoading.value = false;
    state.hasAdditionalInfoError.value = false;
  }

  // on color label change
  void onSuperAttributeChange(Option newOption) {
    debugPrint('onSuperAttributeChange');
    state.selectedOption.value = newOption;
    state.selectedProduct.value = newOption.variants.products?.first;
  }

  // on size change
  void onInnerAttributeChange(ProductModel newProduct) {
    debugPrint('onInnerAttributeChange');
    state.selectedProduct.value = newProduct;
  }

  // on simple attribute change
  void onSimpleAttributeChange(SimpleOption option) {
    debugPrint('onInnerAttributeChange');
    state.selectedProduct.value = option.product;
    state.selectedSimpleOption.value = option;
  }

  // add to card
  Future<void> onAddToCart(BuildContext context, ProductModel product) async {
    debugPrint('addToCart');

    if (!loginStatusController.loginStatus) {
      navigateToLoginScreen();
      showSnack('warning'.tr, 'please_login_to_add_cart'.tr, SnackType.WARNING);
      return;
    }

    final Map<String, dynamic> params = {
      'product_id': product.id,
      'quantity': addingItemCount.value,
    };

    await state.cartController.add(context, params, product.id);
  }

  Future<void> onOrderNowTapped(BuildContext context, ProductModel product) async {
    debugPrint('onOrderNowTapped 2');

    if (!loginStatusController.loginStatus) {
      navigateToLoginScreen();
      showSnack('warning'.tr, 'please_login_to_purchase'.tr, SnackType.WARNING);
      return;
    }

    final Map<String, dynamic> params = {
      'product_id': product.id,
      'quantity': addingItemCount.value,
      'is_buy_now': true,
    };

    await state.cartController.add(context, params, product.id);

    Get.offNamed(AppRoutes.CART_ORDER);
  }

  void onIncreaseItemTapped() {
    debugPrint('onIncreaseItemTapped');
    addingItemCount.obs.value++;

    this.calculateItemTotalPrice();
  }

  void onDecreaseItemTapped() {
    debugPrint('onDecreaseItemTapped');
    if (addingItemCount.obs.value > 1) {
      addingItemCount.obs.value--;
    }

    this.calculateItemTotalPrice();
  }

  void calculateItemTotalPrice() {
    itemTotalPrice.value = this.model.price * addingItemCount.value;
  }

  // closes bottom sheet
  void onCloseNowBtnTapped() {
    snappingSheetController.snapToPosition(
      SnappingPosition.factor(positionFactor: 0.02),
    );
  }

  // on Product specification tab change
  void onTapChange(int index) {
    debugPrint('onTap change $index');
    state.reviewFocusNode.unfocus();

    if (state.reviews.isEmpty && index == 2) {
      getProductReviews();
    }
  }

  void onReviewRatingUpdate(double rating) {
    debugPrint('rating: $rating');
    state.rating.value = rating;
    state.hasRatingError.value = state.rating.value == 0;
  }

  Future<void> onSubmitReviewTapped(BuildContext context) async {
    debugPrint('onSubmitReviewTapped');

    // check login status
    SharedPreferences prefs = await SharedPreferences.getInstance();
    final bool isLoggedIn = prefs.getBool(Constants.IS_LOGGED_IN) ?? false;

    if (!isLoggedIn) {
      showSnack('warning'.tr, 'please_login'.tr, SnackType.WARNING);
      return;
    }

    // check rating star is tapped
    state.hasRatingError.value = state.rating.value == 0;
    if (state.hasRatingError.value) {
      return;
    }

    // validate comment form
    if (state.reviewFormKey.currentState!.validate()) {
      if (state.rating == 0) {
        return;
      }

      final Map<String, dynamic> params = {
        'comment': state.reviewCtrl.text,
        'rating': state.rating,
        'locale': await getLocale(),
      };

      debugPrint('params $params');

      context.loaderOverlay.show();
      final result = await ProductApi.createProductReviews(params, model.id);
      debugPrint('result $result');

      // if result true, then reset
      if (result) {
        state.reviewFormKey.currentState!.reset();
        state.hasRatingError.value = false;
        state.rating.value = 0.0;
        state.reviewCtrl.text = '';
      } else
        showSnack('error'.tr, 'error_occurred'.tr, SnackType.ERROR);

      context.loaderOverlay.hide();
    }
  }

  Future<void> getProductReviews() async {
    state.isReviewLoading.value = true;
    state.hasReviewError.value = false;

    state.reviews.clear();

    final result = await ProductApi.getProductReviews(model.id);
    state.isReviewLoading.value = false;

    if (result == null) {
      state.hasReviewError.value = true;
      return;
    }

    state.reviews.addAll(result);
  }
}
