import 'dart:io';

import 'package:agile_pay/flutter_pay.dart';
import 'package:carousel_slider/carousel_controller.dart';
import 'package:carousel_slider/carousel_options.dart';
import 'package:flutter/material.dart';
import 'package:injectable/injectable.dart';
import 'package:keyboard/base/base_controller.dart';
import 'package:get/get.dart';
import 'package:keyboard/data/bean/character_info.dart';
import 'package:keyboard/module/store/new_discount/member_card_bean.dart';
import '../../../data/api/response/user_info_response.dart';
import '../../../data/bean/goods_info.dart';
import '../../../data/bean/member_info.dart';
import '../../../data/bean/pay_way_info.dart';
import '../../../data/bean/wechat_payment_sign_bean.dart';
import '../../../data/consts/constants.dart';
import '../../../data/consts/error_code.dart';
import '../../../data/consts/payment_type.dart';
import '../../../data/repository/account_repository.dart';
import '../../../data/repository/store_repository.dart';
import '../../../dialog/alipay_qr_code_dialog.dart';
import '../../../dialog/loading_dialog.dart';
import '../../../dialog/login/login_dialog.dart';
import '../../../dialog/member_agreement_dialog.dart';
import '../../../dialog/payment_fail_dialog.dart';
import '../../../dialog/payment_success_dialog.dart';
import '../../../dialog/wechat_qr_code_dialog.dart';
import '../../../resource/assets.gen.dart';
import '../../../resource/string.gen.dart';
import '../../../utils/async_util.dart';
import '../../../utils/atmob_log.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 '../store_banner_bean.dart';
import '../suprise/surprise_dialog.dart';
import '../ticket/discount_ticket_dialog.dart';
import 'new_discount_page.dart';

@injectable
class NewDiscountController extends BaseController
    implements PaymentStatusCallback {
  final String tag = "NewDiscountController";

  final StoreRepository storeRepository;

  final AccountRepository accountRepository;

  final PaymentStatusManager paymentStatusManager;

  RxList<GoodsInfo> get goodsInfoList =>
      storeRepository.newDiscountGoodsInfoList;

  RxList<PayWayInfo> get payWayList => storeRepository.newDiscountPayWayList;

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

  GoodsInfo? get selectedGoodsInfoItem => _selectedGoodsInfoItem.value;

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

  PayWayInfo? get selectedPayWay => _selectedPayWay.value;

  CancelableFuture? _storeDataFuture;

  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;

  RxList<CharacterInfo> get _charactersList => storeRepository.charactersList;

  List<CharacterInfo> get charactersList => _charactersList;

  final CarouselSliderController carouselSliderController =
      CarouselSliderController();

  final RxInt _currentBanner = 0.obs;

  int get currentBannerIndex => _currentBanner.value;

  /// 轮播图控制器
  final List<AssetGenImage> bannerList = [
    Assets.images.iconNewDiscountBanner1,

    Assets.images.iconNewDiscountBanner2,

    Assets.images.iconNewDiscountBanner3,
  ];

  final List<MemberCardBean> memberCardList = [
    MemberCardBean(
      imageUrl: Assets.images.iconNewDiscountMembershipCard1,
      title: StringName.newDiscountMemberCard1Title,
      desc: StringName.newDiscountMemberCard1Desc,
      gradient: LinearGradient(
        begin: Alignment(0.50, -0.00),
        end: Alignment(0.50, 1.00),
        colors: [const Color(0xFFF1EDFF), const Color(0xFFFAF8FF)],
      ),
    ),
    MemberCardBean(
      imageUrl: Assets.images.iconNewDiscountMembershipCard2,
      title: StringName.newDiscountMemberCard2Title,
      desc: StringName.newDiscountMemberCard2Desc,
      gradient: LinearGradient(
        begin: Alignment(0.50, -0.00),
        end: Alignment(0.50, 1.00),
        colors: [const Color(0xFFDCF4C0), const Color(0xFFFAFFF3)],
      ),
    ),
    MemberCardBean(
      imageUrl: Assets.images.iconNewDiscountMembershipCard3,
      title: StringName.newDiscountMemberCard3Title,
      desc: StringName.newDiscountMemberCard3Desc,
      gradient: LinearGradient(
        begin: Alignment(0.50, -0.00),
        end: Alignment(0.50, 1.00),
        colors: [const Color(0xFFF9DBFF), const Color(0xFFFFFBFE)],
      ),
    ),
    MemberCardBean(
      imageUrl: Assets.images.iconNewDiscountMembershipCard4,
      title: StringName.newDiscountMemberCard4Title,
      desc: StringName.newDiscountMemberCard4Desc,
      gradient: LinearGradient(
        begin: Alignment(0.50, -0.00),
        end: Alignment(0.50, 1.00),
        colors: [const Color(0xFFDBECFF), const Color(0xFFFBFBFF)],
      ),
    ),
    MemberCardBean(
      imageUrl: Assets.images.iconNewDiscountMembershipCard5,
      title: StringName.newDiscountMemberCard5Title,
      desc: StringName.newDiscountMemberCard5Desc,
      gradient: LinearGradient(
        begin: Alignment(0.50, -0.00),
        end: Alignment(0.50, 1.00),
        colors: [const Color(0xFFFFF7DB), const Color(0xFFFFFDFB)],
      ),
    ),
  ];

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

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

  void refreshStoreData() {
    storeRepository.refreshNewDiscountGoodsInfoList();
  }

  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(),
    );
    if (filteredGoodsList.isNotEmpty) {
      _selectedGoodsInfoItem.value = filteredGoodsList.first;
    }
  }

  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);
              LoginDialog.show();
            } 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 onInit() {
    super.onInit();

    if (goodsInfoList.isNotEmpty) {
      _selectedGoodsInfoItem.value = goodsInfoList.first;
    }

    if (payWayList.isNotEmpty) {
      _selectedPayWay.value = payWayList.first;
      updateFilteredGoodsList();
    }

    ever<List<GoodsInfo>>(goodsInfoList, (list) {
      if (list.isNotEmpty) {
        _selectedGoodsInfoItem.value = list.first;
      }
    });

    ever<List<PayWayInfo>>(payWayList, (list) {
      if (list.isNotEmpty) {
        _selectedPayWay.value = list.first;
        updateFilteredGoodsList();
      }
    });
  }

  @override
  void onClose() {
    super.onClose();
    _storeDataFuture?.cancel();
    paymentStatusManager.unregisterPaymentSuccessCallback(this);
    if (!isFirstIntoDiscount() && !accountRepository.isVipUser) {
      if (Platform.isAndroid) {
        SurpriseDialog.show(
          clickConfirm: () {
            NewDiscountPage.start();
          },
          clickCancel: () {},
        );
      }
      if (Platform.isIOS) {
        DiscountTicketDialog.show(
          clickConfirm: () {
            NewDiscountPage.start();
          },
          clickCancel: () {},
        );

      }
    } else {
      setFirstIntoDiscount(false);
    }
  }

  @override
  void onPaymentSuccess(
    String orderNo,
    PayWayInfo payWayInfo,
    GoodsInfo goodsInfo,
  ) {
    LoadingDialog.hide();
    AtmobLog.d(tag, 'onPaymentSuccess: $orderNo');
    Get.back();
    PaymentSuccessDialog.show(
      goodsInfo: goodsInfo,
      btnConfirm: () {
        AtmobLog.d(tag, 'onGoodsItemClick: ${goodsInfo.toJson()}');
      },
    );
  }
}
