import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:in_app_purchase/in_app_purchase.dart';

import 'ad_config.dart';

/// Wraps the non-consumable `remove_ads` purchase. On any verified purchase
/// or restore of the product it invokes [onEntitlementGranted]; the caller
/// flips the AdsRemovedNotifier. All failures are swallowed.
class IapService {
  IapService({required this.onEntitlementGranted});

  final Future<void> Function() onEntitlementGranted;
  final InAppPurchase _iap = InAppPurchase.instance;
  StreamSubscription<List<PurchaseDetails>>? _sub;
  ProductDetails? _product;

  bool get available => _available;
  bool _available = false;

  ProductDetails? get product => _product;

  Future<void> initialize() async {
    try {
      _available = await _iap.isAvailable();
      if (!_available) return;
      _sub = _iap.purchaseStream.listen(_onPurchases,
          onError: (_) {}, cancelOnError: false);
      final response =
          await _iap.queryProductDetails({AdConfig.removeAdsProductId});
      if (response.productDetails.isNotEmpty) {
        _product = response.productDetails.first;
      }
    } catch (e) {
      debugPrint('IAP init failed: $e');
    }
  }

  Future<void> buyRemoveAds() async {
    final product = _product;
    if (product == null) return;
    try {
      await _iap.buyNonConsumable(
          purchaseParam: PurchaseParam(productDetails: product));
    } catch (e) {
      debugPrint('IAP buy failed: $e');
    }
  }

  Future<void> restorePurchases() async {
    try {
      await _iap.restorePurchases();
    } catch (e) {
      debugPrint('IAP restore failed: $e');
    }
  }

  Future<void> _onPurchases(List<PurchaseDetails> purchases) async {
    for (final p in purchases) {
      if (p.productID != AdConfig.removeAdsProductId) continue;
      if (p.status == PurchaseStatus.purchased ||
          p.status == PurchaseStatus.restored) {
        await onEntitlementGranted();
      }
      if (p.pendingCompletePurchase) {
        await _iap.completePurchase(p);
      }
    }
  }

  void dispose() => _sub?.cancel();
}
