import ComponentLibrary
import ComposableArchitecture
import Localization
import SwiftUI

public struct MadlibsOnboardingContainerView: View {
    @Bindable var store: StoreOf<MadlibsContainerReducer>

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

    public var body: some View {
        StepContainerView(store: store)
            .background(
                background
                    .ignoresSafeArea()
            )
            .onAppear {
                store.send(.onAppear)
            }
    }

    private var background: some View {
        MadlibsBackgroundView(
            auraShaderId: "madlibs-onboarding-container-background"
        )
    }
}

// MARK: - StepContainerView

private struct StepContainerView: View {
    @Bindable var store: StoreOf<MadlibsContainerReducer>
    @FocusState private var persistentKeyboardFocus: Bool

    var body: some View {
        content
    }

    private var content: some View {
        VStack {
            headerContent

            stepContent
                .id(store.currentStep)
                .frame(maxWidth: .infinity, maxHeight: .infinity)
                .transition(store.navigationDirection.transition)
                .animation(.easeInOut(duration: 0.3), value: store.currentStep)
                .onChange(of: store.currentStep) { _, newValue in
                    // Maintain keyboard focus when transitioning between text input steps
                    if store.state.shouldMaintainKeyboard(to: newValue) {
                        // Keep focus active during transition
                        persistentKeyboardFocus = true
                    }
                }
        }
        .padding(MadlibsContainerConstants.screenEdgePadding)
        .safeAreaInset(edge: .bottom) {
            bottomSafeAreaContent
                .padding(MadlibsContainerConstants.bottomSafeAreaPadding)
        }
    }

    private var headerContent: some View {
        struct ProgressData: Hashable {
            let step: MadlibsContainerReducer.State.ProfileSetupStep
            let isActive: Bool
        }

        let progressData = store.progressSteps.map { step in
            ProgressData(step: step, isActive: store.state.shouldShowProgress(for: step))
        }

        return MadlibsHeaderView(
            leadingButton: .init(
                icon: .back,
                showing: store.shouldShowBackButton,
                disabled: !store.canNavigateBack,
                action: { store.send(.backTapped) }
            ),
            skipButton: .init(
                showing: store.shouldShowSkipButton,
                disabled: !store.canSkip,
                action: { store.send(.skipTapped) }
            ),
            showProgressBar: store.shouldShowProgressBar,
            progressSteps: progressData,
            isStepActive: \.isActive
        )
    }

    @ViewBuilder
    private var stepContent: some View {
        switch store.currentStep {
        case .musicGenre:
            MusicGenrePickerScreen(
                store: store.scope(state: \.musicGenreState, action: \.musicGenre)
            )
            .onAppear {
                store.send(.onStepAppear(store.currentStep))
            }

        case .displayName:
            if let displayNameStore = store.scope(state: \.displayNameState, action: \.displayName) {
                MadlibsNameEntryScreen(store: displayNameStore)
                    .onAppear {
                        store.send(.onStepAppear(store.currentStep))
                    }
            }

        case .username:
            if let usernameStore = store.scope(state: \.usernameState, action: \.username) {
                MadlibsUsernameEntryScreen(store: usernameStore)
                    .onAppear {
                        store.send(.onStepAppear(store.currentStep))
                    }
            }

        case .birthday:
            if let birthdayStore = store.scope(state: \.birthdayState, action: \.birthday) {
                MadlibsBirthdayEntryScreen(store: birthdayStore)
                    .onAppear {
                        store.send(.onStepAppear(store.currentStep))
                    }
            }

        case .notifications:
            if let notificationsStore = store.scope(state: \.notificationsState, action: \.notifications) {
                MadlibsNotificationsScreen(store: notificationsStore)
                    .onAppear {
                        store.send(.onStepAppear(store.currentStep))
                    }
            }
        }
    }

    @ViewBuilder
    private var bottomSafeAreaContent: some View {
        VStack {
            auraButton(
                title: primaryButtonTitle,
                isLoading: store.isNextButtonLoading,
                action: primaryButtonAction
            )

            bottomSafeAreaSecondaryContent(
                isLoading: store.isSecondaryButtonLoading
            )
            .transition(.asymmetric(
                insertion: .move(edge: .bottom).combined(with: .opacity),
                removal: .move(edge: .bottom).combined(with: .opacity)
            ))
        }
        .animation(.easeInOut(duration: 0.3), value: store.currentStep)
    }

    @ViewBuilder
    private func bottomSafeAreaSecondaryContent(
        isLoading: Bool
    ) -> some View {
        switch store.currentStep {
        case .notifications:
            if store.shouldForceHideSecondaryButton {
                EmptyView()
            } else {
                PrimaryButtonV1(
                    title: L10n.FeatureOnboarding.madlibsNotificationsPromptSecondaryCta,
                    isLoading: isLoading,
                    colorCombination: .darkAlways,
                    preferredSize: .large,
                    action: { store.send(.nextTapped) }
                )
                .clipShape(.capsule)
            }

        case .musicGenre,
             .displayName,
             .username,
             .birthday:
            EmptyView()
        }
    }

    private var primaryButtonTitle: String {
        switch store.currentStep {
        case .notifications:
            L10n.FeatureOnboarding.madlibsNotificationsPromptPrimaryCta

        case .musicGenre,
             .displayName,
             .username,
             .birthday:
            L10n.FeatureOnboarding.next
        }
    }

    private var primaryButtonAction: () -> Void {
        switch store.currentStep {
        case .notifications:
            { store.send(.notifications(.tappedShowNotification)) }
        case .musicGenre,
             .displayName,
             .username,
             .birthday:
            { store.send(.nextTapped) }
        }
    }

    private func auraButton(
        title: String,
        isLoading: Bool = false,
        action: @escaping () -> Void
    ) -> some View {
        AuraButton(
            title: title,
            isLoading: isLoading,
            auraStyle: .orangeAura,
            withGradientOverlay: false,
            action: action
        )
        .contentTransition(.identity)
        .disabled(!store.canNavigateNext || isLoading)
        .opacity((store.canNavigateNext && !isLoading) ? 1.0 : 0.4)
    }
}

private extension MadlibsContainerReducer.State.NavigationDirection {
    var transition: AnyTransition {
        switch self {
        case .forward:
            return .asymmetric(
                insertion: .opacity
                    .combined(with: .offset(y: 40))
                    .animation(.easeOut(duration: 0.3)),
                removal: .opacity
                    .animation(.easeIn(duration: 0.2))
            )

        case .backward:
            return .asymmetric(
                insertion: .opacity
                    .combined(with: .offset(y: -40))
                    .animation(.easeOut(duration: 0.3)),
                removal: .opacity
                    .animation(.easeIn(duration: 0.2))
            )
        }
    }
}
