// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

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

import 'enum_converters.dart';
import 'sk_payment_queue_wrapper.dart';
import 'sk_product_wrapper.dart';

part 'sk_payment_transaction_wrappers.g.dart';

/// Callback handlers for transaction status changes.
///
/// Must be subclassed. Must be instantiated and added to the
/// [SKPaymentQueueWrapper] via [SKPaymentQueueWrapper.setTransactionObserver]
/// at app launch.
///
/// This class is a Dart wrapper around [SKTransactionObserver](https://developer.apple.com/documentation/storekit/skpaymenttransactionobserver?language=objc).
abstract class SKTransactionObserverWrapper {
  /// Triggered when any transactions are updated.
  void updatedTransactions(
      {required List<SKPaymentTransactionWrapper> transactions});

  /// Triggered when any transactions are removed from the payment queue.
  void removedTransactions(
      {required List<SKPaymentTransactionWrapper> transactions});

  /// Triggered when there is an error while restoring transactions.
  void restoreCompletedTransactionsFailed({required SKError error});

  /// Triggered when payment queue has finished sending restored transactions.
  void paymentQueueRestoreCompletedTransactionsFinished();

  /// Triggered when a user initiates an in-app purchase from App Store.
  ///
  /// Return `true` to continue the transaction in your app. If you have
  /// multiple [SKTransactionObserverWrapper]s, the transaction will continue if
  /// any [SKTransactionObserverWrapper] returns `true`. Return `false` to defer
  /// or cancel the transaction. For example, you may need to defer a
  /// transaction if the user is in the middle of onboarding. You can also
  /// continue the transaction later by calling [addPayment] with the
  /// `payment` param from this method.
  bool shouldAddStorePayment(
      {required SKPaymentWrapper payment, required SKProductWrapper product});
}

/// The state of a transaction.
///
/// Dart wrapper around StoreKit's
/// [SKPaymentTransactionState](https://developer.apple.com/documentation/storekit/skpaymenttransactionstate?language=objc).
enum SKPaymentTransactionStateWrapper {
  /// Indicates the transaction is being processed in App Store.
  ///
  /// You should update your UI to indicate that you are waiting for the
  /// transaction to update to another state. Never complete a transaction that
  /// is still in a purchasing state.
  @JsonValue(0)
  purchasing,

  /// The user's payment has been succesfully processed.
  ///
  /// You should provide the user the content that they purchased.
  @JsonValue(1)
  purchased,

  /// The transaction failed.
  ///
  /// Check the [SKPaymentTransactionWrapper.error] property from
  /// [SKPaymentTransactionWrapper] for details.
  @JsonValue(2)
  failed,

  /// This transaction is restoring content previously purchased by the user.
  ///
  /// The previous transaction information can be obtained in
  /// [SKPaymentTransactionWrapper.originalTransaction] from
  /// [SKPaymentTransactionWrapper].
  @JsonValue(3)
  restored,

  /// The transaction is in the queue but pending external action. Wait for
  /// another callback to get the final state.
  ///
  /// You should update your UI to indicate that you are waiting for the
  /// transaction to update to another state.
  @JsonValue(4)
  deferred,

  /// Indicates the transaction is in an unspecified state.
  @JsonValue(-1)
  unspecified,
}

/// Created when a payment is added to the [SKPaymentQueueWrapper].
///
/// Transactions are delivered to your app when a payment is finished
/// processing. Completed transactions provide a receipt and a transaction
/// identifier that the app can use to save a permanent record of the processed
/// payment.
///
/// Dart wrapper around StoreKit's
/// [SKPaymentTransaction](https://developer.apple.com/documentation/storekit/skpaymenttransaction?language=objc).
@JsonSerializable(createToJson: true)
@immutable
class SKPaymentTransactionWrapper {
  /// Creates a new [SKPaymentTransactionWrapper] with the provided information.
  // TODO(stuartmorgan): Temporarily ignore const warning in other parts of the
  // federated package, and remove this.
  // ignore: prefer_const_constructors_in_immutables
  SKPaymentTransactionWrapper({
    required this.payment,
    required this.transactionState,
    this.originalTransaction,
    this.transactionTimeStamp,
    this.transactionIdentifier,
    this.error,
  });

  /// Constructs an instance of this from a key value map of data.
  ///
  /// The map needs to have named string keys with values matching the names and
  /// types of all of the members on this class. The `map` parameter must not be
  /// null.
  factory SKPaymentTransactionWrapper.fromJson(Map<String, dynamic> map) {
    return _$SKPaymentTransactionWrapperFromJson(map);
  }

  /// Current transaction state.
  @SKTransactionStatusConverter()
  final SKPaymentTransactionStateWrapper transactionState;

  /// The payment that has been created and added to the payment queue which
  /// generated this transaction.
  final SKPaymentWrapper payment;

  /// The original Transaction.
  ///
  /// Only available if the [transactionState] is [SKPaymentTransactionStateWrapper.restored].
  /// Otherwise the value is `null`.
  ///
  /// When the [transactionState]
  /// is [SKPaymentTransactionStateWrapper.restored], the current transaction
  /// object holds a new [transactionIdentifier].
  final SKPaymentTransactionWrapper? originalTransaction;

  /// The timestamp of the transaction.
  ///
  /// Seconds since epoch. It is only defined when the [transactionState] is
  /// [SKPaymentTransactionStateWrapper.purchased] or
  /// [SKPaymentTransactionStateWrapper.restored].
  /// Otherwise, the value is `null`.
  final double? transactionTimeStamp;

  /// The unique string identifer of the transaction.
  ///
  /// It is only defined when the [transactionState] is
  /// [SKPaymentTransactionStateWrapper.purchased] or
  /// [SKPaymentTransactionStateWrapper.restored]. You may wish to record this
  /// string as part of an audit trail for App Store purchases. The value of
  /// this string corresponds to the same property in the receipt.
  ///
  /// The value is `null` if it is an unsuccessful transaction.
  final String? transactionIdentifier;

  /// The error object
  ///
  /// Only available if the [transactionState] is
  /// [SKPaymentTransactionStateWrapper.failed].
  final SKError? error;

  @override
  bool operator ==(Object other) {
    if (identical(other, this)) {
      return true;
    }
    if (other.runtimeType != runtimeType) {
      return false;
    }
    return other is SKPaymentTransactionWrapper &&
        other.payment == payment &&
        other.transactionState == transactionState &&
        other.originalTransaction == originalTransaction &&
        other.transactionTimeStamp == transactionTimeStamp &&
        other.transactionIdentifier == transactionIdentifier &&
        other.error == error;
  }

  @override
  int get hashCode => Object.hash(payment, transactionState,
      originalTransaction, transactionTimeStamp, transactionIdentifier, error);

  @override
  String toString() => _$SKPaymentTransactionWrapperToJson(this).toString();

  /// The payload that is used to finish this transaction.
  Map<String, String?> toFinishMap() => <String, String?>{
        'transactionIdentifier': transactionIdentifier,
        'productIdentifier': payment.productIdentifier,
      };
}
