import 'package:agile_pay/flutter_pay.dart';
import 'package:carousel_slider/carousel_controller.dart';
import 'package:carousel_slider/carousel_options.dart';
import 'package:flutter/cupertino.dart';
import 'package:get/get.dart';
import 'package:injectable/injectable.dart';
import 'package:keyboard/base/base_controller.dart';
import 'package:keyboard/data/bean/pay_way_info.dart';
import 'package:keyboard/data/bean/goods_info.dart';
import 'package:keyboard/data/repository/account_repository.dart';
import 'package:keyboard/data/repository/store_repository.dart';
import 'package:keyboard/dialog/payment_fail_dialog.dart';
import 'package:keyboard/dialog/payment_success_dialog.dart';
import 'package:keyboard/module/store/store_banner_bean.dart';
import 'package:keyboard/module/store/store_user_reviews_bean.dart';
import 'package:keyboard/utils/async_util.dart';
import 'package:keyboard/utils/atmob_log.dart';

import '../../data/api/response/user_info_response.dart';
import '../../data/bean/member_info.dart';
import '../../data/bean/wechat_payment_sign_bean.dart';
import '../../data/consts/error_code.dart';
import '../../data/consts/payment_type.dart';
import '../../dialog/alipay_qr_code_dialog.dart';
import '../../dialog/loading_dialog.dart';
import '../../dialog/member_agreement_dialog.dart';
import '../../dialog/wechat_qr_code_dialog.dart';
import '../../resource/assets.gen.dart';
import '../../resource/string.gen.dart';
import '../../utils/date_util.dart';
import '../../utils/error_handler.dart';
import '../../utils/http_handler.dart';
import '../../utils/payment_status_manager.dart';
import '../../utils/toast_util.dart';
import '../login/login_page.dart';

@injectable
class StoreController extends BaseController implements PaymentStatusCallback {
  final tag = 'StoreController';

  final StoreRepository storeRepository;

  final AccountRepository accountRepository;

  final PaymentStatusManager paymentStatusManager;

  final RxList<GoodsInfo> goodsInfoList = <GoodsInfo>[].obs;

  final Rxn<GoodsInfo> _selectedGoodsInfoItem = Rxn<GoodsInfo>();

  GoodsInfo? get selectedGoodsInfoItem => _selectedGoodsInfoItem.value;

  final Rxn<PayWayInfo> _selectedPayWay = Rxn<PayWayInfo>();

  PayWayInfo? get selectedPayWay => _selectedPayWay.value;

  final RxList<PayWayInfo> payWayList = <PayWayInfo>[].obs;

  CancelableFuture? _storeDataFuture;

  String? get phone => accountRepository.loginPhoneNum.value;

  bool get isLogin => accountRepository.isLogin.value;

  final isAgree = false.obs;

  MemberInfo? get memberStatusInfo => accountRepository.memberStatusInfo.value;

  UserInfoResponse? get userInfo => accountRepository.userInfo.value;

  // 过滤不同支付的商品
  final RxList<GoodsInfo> filteredGoodsList = <GoodsInfo>[].obs;

  final List<StoreBannerBean> bannerList = [
    StoreBannerBean(
      banner: Assets.images.iconStoreBanner1,
      indicatorImg: Assets.images.iconStoreIndicator1,
      unSelectedDesc: "助攻追爱",
    ),
    StoreBannerBean(
      banner: Assets.images.iconStoreBanner2,
      indicatorImg: Assets.images.iconStoreIndicator2,
      unSelectedDesc: "定制人设",
    ),
    StoreBannerBean(
      banner: Assets.images.iconStoreBanner3,
      indicatorImg: Assets.images.iconStoreIndicator3,
      unSelectedDesc: "解锁人设",
    ),
  ];

  final List<StoreUserReviewsBean> userReviewsList = [
    StoreUserReviewsBean(
      avatar: Assets.images.iconStoreUserReview1,
      userName: "执****念",
      userReviews: "恋爱键盘超绝！多样人设主题，快捷情话输入，敲出专属浪漫，爱意满屏。1",
    ),
    StoreUserReviewsBean(
      avatar: Assets.images.iconStoreUserReview2,
      userName: "过****人",
      userReviews: "恋爱键盘超绝！多样人设主题，快捷情话输入，敲出专属浪漫，爱意满屏。2",
    ),
    StoreUserReviewsBean(
      avatar: Assets.images.iconStoreUserReview3,
      userName: "不当****solo",
      userReviews: "恋爱键盘超绝！多样人设主题，快捷情话输入，敲出专属浪漫，爱意满屏。3",
    ),
    StoreUserReviewsBean(
      avatar: Assets.images.iconStoreUserReview4,
      userName: "用户*****1234",
      userReviews: "很好，很满意",
    ),
  ];

  final CarouselSliderController carouselSliderController =
      CarouselSliderController();

  final RxInt _currentBanner = 0.obs;

  int get currentBannerIndex => _currentBanner.value;

  StoreController(
    this.storeRepository,
    this.accountRepository,
    this.paymentStatusManager,
  );

  onBannerChanged(int index, CarouselPageChangedReason reason) {
    _currentBanner.value = index;
  }

  void refreshStoreData() {
    _storeDataFuture?.cancel();
    _storeDataFuture = AsyncUtil.retryWithExponentialBackoff(
      () => _requestGoodsInfoList(),
      4,
    );
    _storeDataFuture?.catchError((error) {
      ErrorHandler.toastError(error);
    });
  }

  Future<void> _requestGoodsInfoList() async {
    try {
      final response = await storeRepository.getGoodsInfoList();
      goodsInfoList.clear();
      payWayList.clear();
      _selectedGoodsInfoItem.value = null;
      if (response.goodsInfoList?.isNotEmpty == true) {
        goodsInfoList.addAll(response.goodsInfoList!);
        _selectedGoodsInfoItem.value = goodsInfoList.first;
      }
      if (response.payInfoList?.isNotEmpty == true) {
        payWayList.addAll(response.payInfoList!);
        _selectedPayWay.value = payWayList.first;
        updateFilteredGoodsList();
      }
    } catch (e) {
      AtmobLog.e(tag, e.toString());
    }
  }

  void updateFilteredGoodsList() {
    if (_selectedPayWay.value == null) {
      return;
    }
    _selectedGoodsInfoItem.value = null;
    int selectedPayWayId = _selectedPayWay.value!.id;
    filteredGoodsList.assignAll(
      goodsInfoList.where((goods) {
        return goods.payOptionIds == null ||
            goods.payOptionIds!.contains(selectedPayWayId);
      }).toList(),
    );
  }

  void onGoodsItemClick(GoodsInfo goodsInfo) {
    _selectedGoodsInfoItem.value = goodsInfo;
    debugPrint("'item: ${goodsInfo.toJson()}");
  }

  void clickPayWaySwitch() {
    if (payWayList.isNotEmpty) {
      int currentIndex = payWayList.indexOf(
        _selectedPayWay.value ?? payWayList.first,
      );
      int nextIndex = (currentIndex + 1) % payWayList.length;
      _selectedPayWay.value = payWayList[nextIndex];
      updateFilteredGoodsList(); // 切换支付方式后，更新商品列表
    }
  }

  void clickBack() {
    Get.back();
  }

  void clickPayNow() {
    if (selectedGoodsInfoItem == null) {
      ToastUtil.show(StringName.memberPleaseChoiceGoods);
      return;
    }
    if (selectedPayWay == null) {
      ToastUtil.show(StringName.memberPleaseChoicePayment);
      return;
    }
    if (!isAgree.value) {
      MemberAgreementDialog.show(
        btnConfirm: () {
          isAgree.value = true;
          clickPayNow();
        },
      );
      return;
    }
    AtmobLog.d(tag, 'clickPayNow: ${selectedGoodsInfoItem!.toJson()}');
    final buyGoods = selectedGoodsInfoItem!;
    final buyPayWay = selectedPayWay!;

    int goodsId = buyGoods.id;
    int payPlatform = buyPayWay.payPlatform;
    int payMethod = buyPayWay.payMethod;
    int payWayType = getPayWayType(
      payMethod: payMethod,
      payPlatform: payPlatform,
    );

    LoadingDialog.show(StringName.payLoading);
    storeRepository
        .submitAndRequestPay(
          goodsId: goodsId,
          payPlatform: payPlatform,
          payMethod: payMethod,
        )
        .then((response) {
          if (payWayType == PayWayType.paymentWayWechat) {
            _onWeChatPay(
              response.outTradeNo,
              response.wechatPayPrepayJson!,
              payMethod,
              buyGoods,
              buyPayWay,
            );
          } else if (payWayType == PayWayType.paymentWayWechatScan) {
            _onWechatScanPay(
              response.outTradeNo,
              response.wechatPayQrcodeUrl!,
              buyPayWay,
              buyGoods,
            );
          } else if (payWayType == PayWayType.paymentWayAlipay) {
            _onAliPay(
              response.outTradeNo,
              response.alipayOrderString!,
              payMethod,
              buyGoods,
              buyPayWay,
            );
          } else if (payWayType == PayWayType.paymentWayAlipayScan) {
            _onAliScanPay(
              response.outTradeNo,
              response.alipayQrcodeHtml!,
              buyPayWay,
              buyGoods,
            );
          } else {
            ToastUtil.show(StringName.payNotSupport);
          }
        })
        .catchError((error) {
          if (error is ServerErrorException) {
            if (error.code == ErrorCode.payOrderError) {
              refreshStoreData();
              ToastUtil.show(error.message);
            } else if (error.code == ErrorCode.noLoginError) {
              ToastUtil.show(StringName.accountNoLogin);
              LoginPage.start();
            } else {
              ToastUtil.show(error.message);
              paymentFail();
            }
          } else {
            ToastUtil.show(StringName.memberPaymentFailed);
            paymentFail();
          }
        })
        .whenComplete(() {
          LoadingDialog.hide();
        });
  }

  void paymentFail() {
    PaymentFailDialog.show(
      btnConfirm: () {
        clickPayNow();
      },
    );
  }

  void _onAliScanPay(
    String outTradeNo,
    String qrHtml,
    PayWayInfo payWayInfo,
    GoodsInfo goodsInfo,
  ) {
    AlipayQrCodeDialog.show(
      qrCodeHtml: qrHtml,
      loadSuccessCallback: () {
        checkPaymentStatus(outTradeNo, payWayInfo, goodsInfo);
      },
      onCloseCallback: () async {
        //关闭后再持续查询几秒
        CustomLoadingDialog.show();
        await Future.delayed(Duration(seconds: 4));
        paymentStatusManager.removePollingSubscription(outTradeNo);
        CustomLoadingDialog.hide();
      },
    );
  }

  void _onAliPay(
    String outTradeNo,
    String payJson,
    int payMethod,
    GoodsInfo buyGoods,
    PayWayInfo buyPayWay,
  ) {
    final payInfo = AliPayInfo(payJson);
    requestSdkPay(payInfo, outTradeNo, payMethod, buyGoods, buyPayWay);
  }

  void _onWeChatPay(
    String outTradeNo,
    String payJson,
    int payMethod,
    GoodsInfo buyGoods,
    PayWayInfo buyPayWay,
  ) {
    final bean = WechatPaymentSignBean.stringToBean(payJson);
    final payInfo = WechatPayInfo(
      appId: bean.appId,
      partnerId: bean.partnerId,
      prepayId: bean.prepayId,
      package: bean.package,
      noncestr: bean.nonceStr,
      timestamp: bean.timeStamp,
      sign: bean.sign,
    );
    requestSdkPay(payInfo, outTradeNo, payMethod, buyGoods, buyPayWay);
  }

  void _onWechatScanPay(
    String outTradeNo,
    String qrCodeUrl,
    PayWayInfo payWayInfo,
    GoodsInfo goodsInfo,
  ) {
    WechatQrCodeDialog.show(
      qrCodeUrl: qrCodeUrl,
      loadSuccessCallback: () {
        checkPaymentStatus(outTradeNo, payWayInfo, goodsInfo);
      },
      onCloseCallback: () async {
        //关闭后再持续查询几秒
        CustomLoadingDialog.show();
        await Future.delayed(Duration(seconds: 4));
        paymentStatusManager.removePollingSubscription(outTradeNo);
        CustomLoadingDialog.hide();
      },
    );
  }

  void checkPaymentStatus(
    String orderNo,
    PayWayInfo payWayInfo,
    GoodsInfo goodsInfo, {
    String? receiptData,
  }) {
    paymentStatusManager.registerPaymentSuccessCallback(orderNo, this);
    paymentStatusManager.checkPaymentStatus(
      orderNo,
      payWayInfo,
      goodsInfo,
      receiptData: receiptData,
    );
  }

  void requestSdkPay(
    dynamic payInfo,
    String outTradeNo,
    int payMethod,
    GoodsInfo buyGoods,
    PayWayInfo buyPayWay,
  ) {
    AgilePay.startPay(
      payInfo,
      success: (String? result) {
        LoadingDialog.show(StringName.payQuerypayState);
        checkPaymentStatus(
          outTradeNo,
          buyPayWay,
          buyGoods,
          receiptData: result,
        );
      },
      payError: (int error, String? errorMessage) {
        debugPrint('zk---payError: $error, $errorMessage');
        paymentFail();
        errorPayToast(error);

        errorEventReport(payMethod);
      },
      error: (int errno, String? error) {
        debugPrint('zk---error: $errno, $error');
        errorPayToast(errno);
        errorEventReport(payMethod);
      },
    );
  }

  void errorEventReport(int payMethod) {
    if (payMethod == PayMethod.wechat) {
      // EventHandler.report();
    } else if (payMethod == PayMethod.alipay) {
      // EventHandler.report();
    } else if (payMethod == PayMethod.apple) {
      // EventHandler.report();
    }
  }

  void errorPayToast(int errno) {
    if (errno == AgilePayCode.payCodeNotSupport) {
      ToastUtil.show(StringName.payNotSupport);
    } else if (errno == AgilePayCode.payCodeCancelError) {
      ToastUtil.show(StringName.payUserCancel);
    } else if (errno == AgilePayCode.payCodeWxEnvError) {
      ToastUtil.show(StringName.payWxEvnError);
    } else if (errno == AgilePayCode.payCodeNotConnectStore) {
      ToastUtil.show(StringName.payNotConnectStore);
    } else {
      ToastUtil.show(StringName.payError);
    }
  }

  @override
  void onReady() {
    super.onReady();
    refreshStoreData();
  }

  @override
  void onClose() {
    super.onClose();
    _storeDataFuture?.cancel();
    paymentStatusManager.unregisterPaymentSuccessCallback(this);
  }

  @override
  void onPaymentSuccess(
    String orderNo,
    PayWayInfo payWayInfo,
    GoodsInfo goodsInfo,
  ) {
    PaymentSuccessDialog.show(
      infoText:
          memberStatusInfo?.permanent == true
              ? StringName.paySuccessDialogPermanent
              : "${goodsInfo.name}${DateUtil.fromMillisecondsSinceEpoch('yyyy年MM月dd日', memberStatusInfo?.endTimestamp ?? 0)}${StringName.paySuccessDialogDesc}",
      btnConfirm: () {
        AtmobLog.d(tag, 'onGoodsItemClick: ${goodsInfo.toJson()}');
      },
    );
  }
}
