import 'package:guru_app/database/guru_db.dart';
import 'package:guru_app/financial/asset/assets_model.dart';
import 'package:guru_app/financial/asset/assets_store.dart';
import 'package:guru_app/financial/data/db/order_database.dart';
import 'package:guru_app/financial/manifest/manifest_manager.dart';
import 'package:guru_app/financial/product/product_model.dart';
import 'package:guru_app/financial/reward/reward_model.dart';
import 'package:guru_app/guru_app.dart';
import 'package:guru_utils/extensions/extensions.dart';

/// Created by Haoyi on 2023/2/13

class RewardManager {
  static final RewardManager _instance = RewardManager._();

  static RewardManager get instance => _instance;

  RewardManager._();

  final BehaviorSubject<AssetsStore<Asset>> _assetsStoreSubject =
      BehaviorSubject.seeded(AssetsStore<Asset>.inactive());

  AssetsStore<Asset> get rewardedStore => _assetsStoreSubject.value;

  Stream<AssetsStore<Asset>> get observableAssetStore => _assetsStoreSubject.stream;

  Future init() async {
    await reloadAssets();
  }

  Future switchSession() async {
    reloadAssets();
  }

  Future reloadAssets() async {
    final transactions = await GuruDB.instance
        .selectOrders(method: TransactionMethod.reward, attrs: [TransactionAttributes.asset]);
    final newAssetsStore = AssetsStore<Asset>();
    for (var transaction in transactions) {
      final productId = transaction.productId;
      Log.v("init [Rewards] transaction:${transaction.sku} $productId");
      newAssetsStore.addAsset(Asset(productId, transaction));
    }
    _assetsStoreSubject.addEx(newAssetsStore);
  }

  Future<RewardProduct> buildRewardProduct(TransactionIntent intent) async {
    final manifest = await ManifestManager.instance.createManifest(intent);
    return RewardProduct(intent.productId, manifest);
  }

  Future<bool> claim(RewardProduct product, {String from = ""}) async {
    Log.v("rewarded");
    // 如果得到的奖励是可消耗的物品（金币，Joker等），这里将直接领取成功
    if (product.productId.isConsumable) {
      ManifestManager.instance.deliver(product.manifest, TransactionMethod.reward);
      return true;
    }

    final order = product.createOrder();
    final result = await GuruDB.instance.upsertOrder(order: order).catchError((error, stacktrace) {
      Log.v("refreshTransaction error!$error $stacktrace");
      return false;
    });
    if (result) {
      final newAssetsStore = rewardedStore.clone();
      newAssetsStore.addAsset(Asset(product.productId, order));
      _assetsStoreSubject.addEx(newAssetsStore);
    }
    ManifestManager.instance.deliver(product.manifest, TransactionMethod.reward);
    return result;
  }
}
