import APIClient
import ComposableArchitecture
import StatsigClient
import SwiftUI

@Reducer
public struct Paywall {
    @Reducer(state: .equatable)
    public enum Destination {
        case paywallV1(PaywallV1)
        case paywallV2(PaywallV2)
    }

    public enum Delegate {
        case billingInfoResult(Result<SubscriptionInfoResponse, Error>)
    }

    @ObservableState
    public struct State: Equatable {
        @Presents public var destination: Destination.State?

        public init() {
            ParameterStores.General.markExposed(flag: \.$paywallV2)
            if FeatureFlag.general.paywallV2 {
                self.destination = .paywallV2(.init())
            } else {
                self.destination = .paywallV1(.init())
            }
        }
    }

    public enum Action {
        case destination(PresentationAction<Destination.Action>)
        case delegate(Delegate)
        case dismiss
    }

    @Dependency(\.dismiss) var dismiss

    public init() {}

    public var body: some ReducerOf<Self> {
        Reduce { state, action in
            switch action {
            case .destination(.presented(.paywallV1(.billingInfoResult(let result)))):
                return .send(.delegate(.billingInfoResult(result)))

            case .destination(.presented(.paywallV2(.billingInfoResult(let result)))):
                return .send(.delegate(.billingInfoResult(result)))

            case .destination:
                return .none

            case .delegate:
                return .none

            case .dismiss:
                switch state.destination {
                case .paywallV1:
                    return .run { send in
                        await send(.destination(.presented(.paywallV1(.dismiss))))
                        await self.dismiss()
                    }

                case .paywallV2:
                    return .run { send in
                        await send(.destination(.presented(.paywallV2(.dismiss))))
                        await self.dismiss()
                    }

                case .none:
                    return .run { _ in
                        await self.dismiss()
                    }
                }
            }
        }
        .ifLet(\.$destination, action: \.destination)
    }
}

public struct PaywallScreen: View {
    @Bindable private var store: StoreOf<Paywall>

    public init(store: StoreOf<Paywall>) {
        self.store = store
    }

    public var body: some View {
        if let paywallV1Store = store.scope(state: \.destination?.paywallV1, action: \.destination.paywallV1) {
            PaywallScreenV1(store: paywallV1Store)
        } else if let paywallV2Store = store.scope(state: \.destination?.paywallV2, action: \.destination.paywallV2) {
            PaywallScreenV2(store: paywallV2Store)
        }
    }
}
