import Foundation import StoreKit enum PaywallPlan: String, CaseIterable, Identifiable { case monthly case yearly case lifetime var id: String { rawValue } var productID: String { switch self { case .monthly: SubscriptionProductID.monthly case .yearly: SubscriptionProductID.yearly case .lifetime: SubscriptionProductID.lifetime } } func planCopy(from config: PaywallConfig) -> PaywallConfig.PlanCopy { switch self { case .monthly: config.plans.monthly case .yearly: config.plans.yearly case .lifetime: config.plans.lifetime } } func localizedPrice(from product: Product?, config: PaywallConfig) -> String { product?.displayPrice ?? planCopy(from: config).fallbackPrice } func localizedSubtitle(from product: Product?, config: PaywallConfig) -> String { guard let product else { return config.loadingPrice } let copy = planCopy(from: config) return copy.subtitleTemplate.replacingOccurrences(of: "{price}", with: product.displayPrice) } func localizedCTATitle(from product: Product?, config: PaywallConfig) -> String { guard let product else { return config.loadingCTA } let copy = planCopy(from: config) return copy.ctaTemplate.replacingOccurrences(of: "{price}", with: product.displayPrice) } func localizedRenewalDisclosure(from product: Product?, config: PaywallConfig) -> String { switch self { case .lifetime: return config.lifetimeDisclosure case .monthly, .yearly: guard let product else { return config.loadingDisclosure } let price = product.displayPrice let period = product.subscription.map { config.subscriptionPeriodDescription(from: $0.subscriptionPeriod) } ?? config.messages.periodFallback return config.subscriptionDisclosureTemplate .replacingOccurrences(of: "{price}", with: price) .replacingOccurrences(of: "{period}", with: period) } } func fallbackBillingDescription(config: PaywallConfig) -> String { let copy = planCopy(from: config) return copy.fallbackBillingDescription .replacingOccurrences(of: "{price}", with: copy.fallbackPrice) } }