//
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//

import Foundation

extension Stripe {
    /// Create a payment method entry with the Signal service for a subscription
    /// processed by Stripe.
    ///
    /// - Returns
    /// A Stripe secret used to authorize payment for the new subscription.
    public static func createSignalPaymentMethodForSubscription(subscriberId: Data) -> Promise<String> {
        return firstly {
            let request = OWSRequestFactory.subscriptionCreateStripePaymentMethodRequest(subscriberID: subscriberId)

            return networkManager.makePromise(request: request)
        }.map(on: DispatchQueue.global()) { response in
            let statusCode = response.responseStatusCode

            guard statusCode == 200 else {
                throw OWSAssertionError("Got bad response code \(statusCode).")
            }

            guard let parser = ParamParser(responseObject: response.responseBodyJson) else {
                throw OWSAssertionError("Missing or invalid response.")
            }

            do {
                let clientSecret: String = try parser.required(key: "clientSecret")
                return clientSecret
            } catch {
                throw OWSAssertionError("Missing clientID key")
            }
        }
    }

    /// Perform the relevant Stripe API calls to set up a new subscription with
    /// the given client secret and payment method.
    ///
    /// - Parameter clientSecret
    /// A Stripe secret retrieved from the Signal service, used to authorize
    /// payment for the new subscription. See ``createSignalPaymentMethodForSubscription(withSubscriberId:)``.
    /// - Returns
    /// The new payment ID.
    public static func setupNewSubscription(
        clientSecret: String,
        paymentMethod: PaymentMethod
    ) -> Promise<ConfirmedSetupIntent> {
        firstly {
            createPaymentMethod(with: paymentMethod)
        }.then(on: DispatchQueue.sharedUserInitiated) { paymentMethodId -> Promise<ConfirmedSetupIntent> in
            // Pass in the correct callback URL
            confirmSetupIntent(
                mandate: paymentMethod.mandate,
                paymentMethodId: paymentMethodId,
                clientSecret: clientSecret,
                callbackURL: paymentMethod.callbackURL
            )
        }
    }
}
