import 'dart:io';

import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/service/logging.dart';
import 'package:flutter/services.dart';
import 'package:purchases_flutter/purchases_flutter.dart';
import 'package:aitrainer_app/model/product.dart' as wtproduct;

class RevenueCatPurchases with Logging {
  static final RevenueCatPurchases _singleton = RevenueCatPurchases._internal();
  Offering? _offering;
  String? appUserId;

  factory RevenueCatPurchases() {
    return _singleton;
  }

  RevenueCatPurchases._internal();

  Offering? get offering => _offering;

  Future<void> initPlatform() async {
    if (Cache().userLoggedIn != null) {
      await Purchases.setDebugLogsEnabled(true);
      await Purchases.setup("yLxGFWaeRtThLImqznvBnUEKjgArSsZE", appUserId: Cache().userLoggedIn!.customerId.toString());
      appUserId = await Purchases.appUserID;
      log("AppUserId: $appUserId");
      await Purchases.setAllowSharingStoreAccount(true);
      await this.restore();
    }
  }

  Future<void> restore() async {
    if (appUserId != null) {
      try {
        //PurchaserInfo purchaserInfo = await Purchases.restoreTransactions();
        PurchaserInfo purchaserInfo = await Purchases.getPurchaserInfo();
        if (purchaserInfo.entitlements.all["wt_subscription"] != null && purchaserInfo.entitlements.all["wt_subscription"]!.isActive) {
          Cache().hasPurchased = true;
          log(" ******************************************** ");
          log(" Purchase active ! ");
        } else {
          log(" ** No subscription active");
        }
      } on PlatformException catch (e) {
        log("Purchaserinfo not reachable " + e.toString());
      }
    }
    if (Cache().userLoggedIn!.admin == 1) {
      Cache().hasPurchased = true;
    }
  }

  Future<Offering?> getOfferings() async {
    if (appUserId == null) {
      await initPlatform();
    }
    log(" .. acessing offerings...");
    try {
      Offerings offerings = await Purchases.getOfferings();
      if (offerings.current != null && offerings.current!.availablePackages.isNotEmpty) {
        // Display packages for sale
        _offering = offerings.current;
      } else {
        log("No current offerings");
      }
    } on PlatformException catch (e) {
      // optional error handling
      log("!!!! Getting offerings error " + e.toString());
    }
    return _offering;
  }

  Future<void> makePurchase(wtproduct.Product product) async {
    try {
      if (_offering == null) {
        _offering = await getOfferings();
      }
      if (_offering != null) {
        String productId = Platform.isAndroid ? product.productIdAndroid! : product.productIdIos!;
        Package? selectedPackage;
        log("Nr of packages: " + _offering!.availablePackages.length.toString() + " ProductId: " + productId);
        for (var package in _offering!.availablePackages) {
          log("package to check " + package.product.identifier.toString());
          if (package.product.identifier == productId) {
            selectedPackage = package;
            log("**** Selected package to purchase" + package.product.identifier);
            break;
          }
        }
        if (selectedPackage != null) {
          PurchaserInfo purchaserInfo = await Purchases.purchasePackage(selectedPackage);
          if (purchaserInfo.entitlements.all["wt_subscription"] != null && purchaserInfo.entitlements.all["wt_subscription"]!.isActive) {
            Cache().hasPurchased = true;
          }
        } else {
          log("!!!! No Selected package to purchase");
          throw Exception("Purchase was not successful");
        }
      } else {
        log("!!!! No active offering");
      }
    } on PlatformException catch (e) {
      var errorCode = PurchasesErrorHelper.getErrorCode(e);
      if (errorCode == PurchasesErrorCode.invalidReceiptError) {
        log("iOS Sandbox invalid receipt");
        Cache().hasPurchased = true;
        return;
      }
      log(e.toString());
      if (errorCode == PurchasesErrorCode.purchaseCancelledError) {
        throw Exception("Purchase was cancelled");
      } else {
        throw Exception("Purchase was not successful");
      }
    }
  }
}