import 'package:electronic_assistant/base/base_controller.dart';
import 'package:electronic_assistant/data/bean/payment_way.dart';
import 'package:electronic_assistant/data/consts/event_report_id.dart';
import 'package:electronic_assistant/data/repositories/store_repository.dart';
import 'package:electronic_assistant/handler/event_handler.dart';
import 'package:electronic_assistant/module/login/view.dart';
import 'package:electronic_assistant/module/store/payment_status_manager.dart';
import 'package:electronic_assistant/module/store/view.dart';
import 'package:electronic_assistant/resource/string.gen.dart';
import 'package:electronic_assistant/sdk/pay/agile_pay.dart';
import 'package:electronic_assistant/sdk/pay/alipay/ali_pay_info.dart';
import 'package:electronic_assistant/sdk/pay/applepay/apple_pay_info.dart';
import 'package:electronic_assistant/sdk/pay/code/agile_pay_code.dart';
import 'package:electronic_assistant/utils/http_handler.dart';
import 'package:electronic_assistant/utils/toast_util.dart';
import 'package:flutter/widgets.dart';
import 'package:get/get.dart';
import '../../data/api/response/order_pay_response.dart';
import '../../data/api/response/user_info_response.dart';
import '../../data/bean/store_item.dart';
import '../../data/bean/wechat_payment_sign_bean.dart';
import '../../data/consts/constants.dart';
import '../../data/consts/error_code.dart';
import '../../data/repositories/account_repository.dart';
import '../../dialog/loading_dialog.dart';
import '../../sdk/pay/assist/product_type.dart';
import '../../sdk/pay/wxpay/wechat_pay_info.dart';

class StoreController extends BaseController implements PaymentStatusCallback {
  final isExpanded = false.obs;

  final RxList<StoreItem> storeItems = <StoreItem>[].obs;

  final RxList<PaymentWay> paymentWays = <PaymentWay>[].obs;

  final Rxn<StoreItem> currentSelectedStoreItem = Rxn<StoreItem>();

  final Rxn<PaymentWay> currentSelectedPaymentWay = Rxn<PaymentWay>();

  final RxBool isPaymentWayExpanded = true.obs;

  final Rxn<UserInfoResponse> _userInfo = accountRepository.userInfo;

  UserInfoResponse? get userInfo => _userInfo.value;

  StoreFromType? fromType;

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

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

  void _initArgs() {
    fromType = Get.arguments?['fromType'];
    if (fromType == StoreFromType.home) {
      EventHandler.report(EventId.event_104001, params: {'id': '001'});
    } else if (fromType == StoreFromType.mine) {
      EventHandler.report(EventId.event_104001, params: {'id': '002'});
    } else if (fromType == StoreFromType.analyse) {
      EventHandler.report(EventId.event_104001, params: {'id': '003'});
    }
  }

  void initStoreIndexData() {
    storeRepository.storeIndex().then((indexData) {
      storeItems.clear();
      storeItems.addAll(indexData.items);
      currentSelectedStoreItem.value =
          storeItems.isNotEmpty ? storeItems.first : null;

      paymentWays.clear();
      paymentWays.addAll(indexData.paymentWays);
      currentSelectedPaymentWay.value =
          paymentWays.isNotEmpty ? paymentWays.first : null;
    });
  }

  onStoreItemClick(StoreItem storeItem) {
    currentSelectedStoreItem.value = storeItem;
  }

  void onPaymentWayItemClick(PaymentWay paymentWay) {
    currentSelectedPaymentWay.value = paymentWay;
  }

  onBuyClick() async {
    StoreItem? storeItem = currentSelectedStoreItem.value;
    if (storeItem == null) {
      ToastUtil.showToast(StringName.storeChoiceGoods.tr);
      return;
    }
    PaymentWay? paymentWay = currentSelectedPaymentWay.value;
    if (paymentWay == null) {
      ToastUtil.showToast(StringName.storeChoicePayment.tr);
      return;
    }
    int payPlatform = paymentWay.payPlatform;
    int payMethod = paymentWay.payMethod;
    LoadingDialog.show(StringName.storePayLoading.tr);
    try {
      OrderPayResponse response =
          await storeRepository.orderPay(storeItem.id, payPlatform, payMethod);

      dynamic payInfo;
      String outTradeNo = response.outTradeNo;
      if (payPlatform == PayPlatform.android) {
        if (payMethod == PayMethod.alipay) {
          payInfo = AliPayInfo(response.alipayOrderString!);
        } else if (payMethod == PayMethod.wechat) {
          WechatPaymentSignBean bean =
              WechatPaymentSignBean.stringToBean(response.wechatPayPrepayJson!);
          payInfo = WechatPayInfo(
              appId: bean.appId,
              partnerId: bean.partnerId,
              prepayId: bean.prepayId,
              package: bean.package,
              noncestr: bean.nonceStr,
              timestamp: bean.timeStamp,
              sign: bean.sign);
        }
      } else if (payPlatform == PayPlatform.apple) {
        payInfo = ApplePayInfo(
            storeItem.appleGoodsId,
            storeItem.subscribable == 1
                ? ProductType.nonConsumable
                : ProductType.consumable,
            response.appAccountToken);
      }
      Future.delayed(const Duration(seconds: 30), () {
        LoadingDialog.hide();
      });
      AgilePay.startPay(payInfo, success: (String? result) {
        LoadingDialog.show(StringName.storeQueryPayState.tr);
        checkPaymentStatus(outTradeNo, paymentWay, storeItem,
            receiptData: result);
        Future.delayed(const Duration(seconds: 30), () {
          LoadingDialog.hide();
        });
      }, payError: (int error, String? errorMessage) {
        debugPrint('zk---payError: $error, $errorMessage');
        errorPayToast(error);
        errorEventReport(payMethod);
        LoadingDialog.hide();
      }, error: (int errno, String? error) {
        debugPrint('zk---error: $errno, $error');
        errorPayToast(errno);
        errorEventReport(payMethod);
        LoadingDialog.hide();
      });
    } catch (error) {
      LoadingDialog.hide();
      if (error is ServerErrorException &&
          error.code == ErrorCode.errorCodeNoLogin) {
        ToastUtil.showToast(StringName.errorCodeNoLogin.tr);
        LoginPage.start(fromType: LoginFromType.store);
      } else {
        ToastUtil.showToast(StringName.storePayError.tr);
      }
    }
  }

  void errorEventReport(int payMethod) {
    if (payMethod == PayMethod.wechat) {
      EventHandler.report(EventId.event_104003, params: {'id': '001'});
    } else if (payMethod == PayMethod.alipay) {
      EventHandler.report(EventId.event_104003, params: {'id': '002'});
    } else if (payMethod == PayMethod.apple) {
      EventHandler.report(EventId.event_104003, params: {'id': '003'});
    }
  }

  void errorPayToast(int errno) {
    if (errno == AgilePayCode.payCodeNotSupport) {
      ToastUtil.showToast(StringName.storePayNotSupport.tr);
    } else if (errno == AgilePayCode.payCodeCancelError) {
      ToastUtil.showToast(StringName.storePayUserCancel.tr);
    } else if (errno == AgilePayCode.payCodeWxEnvError) {
      ToastUtil.showToast(StringName.storePayWxEvnError.tr);
    } else if (errno == AgilePayCode.payCodeNotConnectStore) {
      ToastUtil.showToast(StringName.storePayNotConnectstore.tr);
    } else {
      ToastUtil.showToast(StringName.storePayError.tr);
    }
  }

  void checkPaymentStatus(
      String orderNo, PaymentWay paymentWay, StoreItem storeItemBean,
      {String? receiptData}) {
    paymentStatusManager.registerPaymentSuccessCallback(orderNo, this);
    paymentStatusManager.checkPaymentStatus(orderNo, paymentWay, storeItemBean,
        receiptData: receiptData);
  }

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

  @override
  void onPaymentSuccess(
      String orderNo, PaymentWay paymentWay, StoreItem storeItemBean) {
    LoadingDialog.hide();
    ToastUtil.showToast(StringName.storePaySuccess.tr);
    Map<String, dynamic> params = {};
    if (paymentWay.payMethod == PayMethod.wechat) {
      params['id'] = '001';
    } else if (paymentWay.payMethod == PayMethod.alipay) {
      params['id'] = '002';
    } else if (paymentWay.payMethod == PayMethod.apple) {
      params['id'] = '003';
    }
    if (fromType == StoreFromType.home) {
      params['from_id'] = '011';
    } else if (fromType == StoreFromType.mine) {
      params['from_id'] = '012';
    } else if (fromType == StoreFromType.analyse) {
      params['from_id'] = '013';
    }
    EventHandler.report(EventId.event_104002, params: params);
    Get.back();
  }
}
