import APIClient
import ComposableArchitecture
import Foundation

@Reducer
public struct ModalReducer {
    public init() {}

    @ObservableState
    public struct State: Equatable {
        public var modals: [Modal]
        public var currentIndex: Int = 0

        public var currentModal: (Modal)? {
            guard currentIndex < modals.count else { return nil }
            return modals[currentIndex]
        }

        public var isLastModal: Bool {
            return currentIndex == modals.count - 1
        }

        public init(modals: [Modal], currentIndex: Int = 0) {
            self.modals = modals
            self.currentIndex = currentIndex
        }

        public static func == (lhs: State, rhs: State) -> Bool {
            return lhs.modals.map(\.id) == rhs.modals.map(\.id) &&
                lhs.currentIndex == rhs.currentIndex
        }
    }

    public enum Action: BindableAction {
        case binding(BindingAction<State>)
        case pageChanged(Int)
        case primaryCTATapped
        case dismiss
        case onAppear
        case delegate(Delegate)

        public enum Delegate: Equatable {
            case handleURL(String)
            case dismissCarousel
        }
    }

    @Dependency(\.dismiss) var dismiss
    @Dependency(\.modalClient) var modalClient

    public var body: some ReducerOf<Self> {
        BindingReducer()

        Reduce { state, action in
            switch action {
            case .binding:
                return .none

            case .onAppear:
                guard let currentModal = state.currentModal else { return .none }
                return .run { _ in
                    await modalClient.markModalAsSeen(currentModal.id)
                }

            case .pageChanged(let newIndex):
                state.currentIndex = newIndex
                guard let currentModal = state.currentModal else { return .none }
                return .run { _ in
                    await modalClient.markModalAsSeen(currentModal.id)
                }

            case .primaryCTATapped:
                guard let currentModal = state.currentModal,
                      let cta = currentModal.primaryCta else {
                    return .none
                }

                return .run { send in
                    await modalClient.markModalAsSeen(currentModal.id)
                    await send(.delegate(.handleURL(cta.url)))
                }

            case .dismiss:
                return .run { [currentModal = state.currentModal] send in
                    if let currentModal {
                        await modalClient.markModalAsSeen(currentModal.id)
                    }
                    await send(.delegate(.dismissCarousel))
                    await self.dismiss()
                }

            case .delegate:
                return .none
            }
        }
    }
}
