import SwiftUI

// MARK: - Auth Screen Enum

enum AuthScreen: Equatable, Identifiable {
    case welcome
    case seedPhrase
    case confirmSeed
    case importSeed
    case setPassword

    var id: Self { self }
}

// MARK: - Auth Coordinator

struct AuthCoordinator: View {
    let onAuthComplete: () -> Void
    var onBackToUnlock: (() -> Void)?
    var initialScreen: AuthScreen = .welcome

    @State private var currentScreen: AuthScreen
    @State private var seedPhrase: [String] = []
    @State private var isImportMode: Bool
    @State private var navigationDirection: NavigationDirection = .forward
    @State private var swipeOffset: CGFloat = 0
    @State private var fadeOverlay: Bool = false
    /// Tracks whether the current drag was identified as a valid horizontal swipe.
    @State private var isSwipeActive = false

    init(
        onAuthComplete: @escaping () -> Void,
        onBackToUnlock: (() -> Void)? = nil,
        initialScreen: AuthScreen = .welcome
    ) {
        self.onAuthComplete = onAuthComplete
        self.onBackToUnlock = onBackToUnlock
        self.initialScreen = initialScreen
        _currentScreen = State(initialValue: initialScreen)
        _isImportMode = State(initialValue: initialScreen == .importSeed)
    }

    private var canSwipeBack: Bool {
        if currentScreen == initialScreen {
            return onBackToUnlock != nil
        }
        return true
    }

    var body: some View {
        GeometryReader { geometry in
            let screenWidth = geometry.size.width

            ZStack {
                RosettaColors.authBackground
                    .ignoresSafeArea()

                // Previous screen — peeks from behind during swipe
                if canSwipeBack {
                    previousScreenView
                        .frame(maxWidth: .infinity, maxHeight: .infinity)
                        .background { RosettaColors.authBackground.ignoresSafeArea() }
                        .offset(x: -screenWidth * 0.3 + swipeOffset * 0.3)
                        .overlay {
                            RosettaColors.Adaptive.background
                                .opacity(swipeOffset > 0
                                    ? 0.5 * (1.0 - swipeOffset / screenWidth)
                                    : 1.0)
                                .ignoresSafeArea()
                        }
                        .allowsHitTesting(false)
                }

                // Current screen — slides right during swipe
                currentScreenView
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
                    .background { RosettaColors.authBackground.ignoresSafeArea() }
                    .transition(.move(edge: navigationDirection == .forward ? .trailing : .leading))
                    .id(currentScreen)
                    .offset(x: swipeOffset)
            }
            .overlay {
                // Fade overlay for smooth forward transitions.
                RosettaColors.Adaptive.background
                    .ignoresSafeArea()
                    .opacity(fadeOverlay ? 1 : 0)
                    .allowsHitTesting(fadeOverlay)
                    .animation(.easeInOut(duration: 0.035), value: fadeOverlay)
            }
            .simultaneousGesture(swipeBackGesture(screenWidth: screenWidth))
        }
    }
}

// MARK: - Screen Views

private extension AuthCoordinator {
    @ViewBuilder
    var currentScreenView: some View {
        switch currentScreen {
        case .welcome:
            WelcomeView(
                onGenerateSeed: { navigateTo(.seedPhrase) },
                onImportSeed: {
                    isImportMode = true
                    navigateTo(.importSeed)
                },
                onBack: onBackToUnlock
            )

        case .seedPhrase:
            SeedPhraseView(
                seedPhrase: $seedPhrase,
                onContinue: { navigateTo(.confirmSeed) },
                onBack: {
                    if initialScreen == .seedPhrase {
                        onBackToUnlock?()
                    } else {
                        navigateBack(to: .welcome)
                    }
                }
            )

        case .confirmSeed:
            ConfirmSeedPhraseView(
                seedPhrase: seedPhrase,
                onConfirmed: {
                    isImportMode = false
                    navigateTo(.setPassword)
                },
                onBack: { navigateBack(to: .seedPhrase) }
            )

        case .importSeed:
            ImportSeedPhraseView(
                seedPhrase: $seedPhrase,
                onContinue: {
                    isImportMode = true
                    navigateTo(.setPassword)
                },
                onBack: {
                    if initialScreen == .importSeed {
                        onBackToUnlock?()
                    } else {
                        navigateBack(to: .welcome)
                    }
                }
            )

        case .setPassword:
            SetPasswordView(
                seedPhrase: seedPhrase,
                isImportMode: isImportMode,
                onAccountCreated: onAuthComplete,
                onBack: {
                    if isImportMode {
                        navigateBack(to: .importSeed)
                    } else {
                        navigateBack(to: .confirmSeed)
                    }
                }
            )
        }
    }

    @ViewBuilder
    var previousScreenView: some View {
        switch currentScreen {
        case .welcome:
            EmptyView()
        case .seedPhrase:
            if initialScreen == .seedPhrase {
                EmptyView()
            } else {
                WelcomeView(onGenerateSeed: {}, onImportSeed: {}, onBack: onBackToUnlock)
            }
        case .confirmSeed:
            SeedPhraseView(seedPhrase: .constant(seedPhrase), onContinue: {}, onBack: {})
        case .importSeed:
            if initialScreen == .importSeed {
                EmptyView()
            } else {
                WelcomeView(onGenerateSeed: {}, onImportSeed: {}, onBack: onBackToUnlock)
            }
        case .setPassword:
            if isImportMode {
                ImportSeedPhraseView(seedPhrase: .constant(seedPhrase), onContinue: {}, onBack: {})
            } else {
                ConfirmSeedPhraseView(seedPhrase: seedPhrase, onConfirmed: {}, onBack: {})
            }
        }
    }
}

// MARK: - Transitions (kept minimal — pure slide, no opacity, to avoid flash)

// MARK: - Navigation

private extension AuthCoordinator {
    func navigateTo(_ screen: AuthScreen) {
        guard !fadeOverlay else { return }
        navigationDirection = .forward
        fadeOverlay = true
        Task { @MainActor in
            try? await Task.sleep(nanoseconds: 35_000_000)
            currentScreen = screen
            try? await Task.sleep(nanoseconds: 10_000_000)
            fadeOverlay = false
        }
    }

    func navigateBack(to screen: AuthScreen) {
        navigationDirection = .backward
        withAnimation(.spring(response: 0.5, dampingFraction: 0.9)) {
            currentScreen = screen
        }
    }
}

// MARK: - Swipe Back Gesture

private extension AuthCoordinator {
    func swipeBackGesture(screenWidth: CGFloat) -> some Gesture {
        DragGesture(minimumDistance: 15)
            .onChanged { value in
                guard canSwipeBack else { return }

                // On first significant movement, determine if this is a horizontal rightward swipe.
                // Ignore vertical drags (let ScrollView handle those).
                if !isSwipeActive && swipeOffset == 0 {
                    let dx = abs(value.translation.width)
                    let dy = abs(value.translation.height)
                    guard dx > dy, value.translation.width > 0 else { return }
                    isSwipeActive = true
                }
                guard isSwipeActive else { return }
                swipeOffset = max(value.translation.width, 0)
            }
            .onEnded { value in
                defer { isSwipeActive = false }
                guard canSwipeBack, swipeOffset > 0 else {
                    swipeOffset = 0
                    return
                }

                let shouldGoBack = value.translation.width > 100
                    || value.predictedEndTranslation.width > 200

                if shouldGoBack {
                    withAnimation(.easeOut(duration: 0.25)) {
                        swipeOffset = screenWidth
                    }
                    DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) {
                        if currentScreen == initialScreen {
                            // Don't reset swipeOffset — keep screen offscreen
                            // while parent performs its own transition.
                            onBackToUnlock?()
                        } else {
                            swipeOffset = 0
                            navigationDirection = .backward
                            currentScreen = backDestination
                        }
                    }
                } else {
                    withAnimation(.spring(response: 0.3, dampingFraction: 0.85)) {
                        swipeOffset = 0
                    }
                }
            }
    }

    var backDestination: AuthScreen {
        switch currentScreen {
        case .welcome: return .welcome
        case .seedPhrase: return .welcome
        case .confirmSeed: return .seedPhrase
        case .importSeed: return .welcome
        case .setPassword: return isImportMode ? .importSeed : .confirmSeed
        }
    }
}

// MARK: - Navigation Direction

private enum NavigationDirection {
    case forward
    case backward
}

#Preview {
    AuthCoordinator(onAuthComplete: {})
}
