import SwiftUI

// Vertical pager — account, tapestry (conditional), feed. The watch's
// UX model is "swipe between glanceable surfaces"; `.verticalPage`
// tabViewStyle is Apple's current watchOS recommendation (WWDC23
// 10031) and pairs naturally with Digital Crown scroll plus the
// watchOS-11 Double Tap scroll integration (WWDC24 10205).
//
// Order rationale (WWDC23 10031 — "Update your app for watchOS 10",
// verticalPage TabView section): "If you have scrollable content
// within a vertical TabView, place it in the last tab whenever
// possible." A List inside `.verticalPage` consumes scroll gestures
// until it hits an edge, then propagates the residual to the
// TabView. Putting the feed last means downward overscroll has no
// tab below to page into — the user can scroll deep into the feed
// without being kicked back to another surface. Account leads
// because it's the glanceable identity surface and barely
// scrollable; tapestry sits in the middle when supported.
//
// The prior 3-tab pager used the legacy ViewBuilder `TabView { ... }`
// initializer, which reconciles children by ordinal position. When
// `auth.supportsTapestry` flipped (initial-false → probed-true, or
// across an account switch to a non-supporting server), every
// sibling tab's `@StateObject` was reinitialized — that was the
// "infinite cycling between tapestry and feed" symptom on real
// hardware. The new value-keyed `Tab(value:)` API (watchOS 11+) keys
// each tab's identity by the Hashable selection value, so adding or
// removing the tapestry tab leaves the feed and account tabs' state
// intact. The default selection is `.feed` by value, not by ordinal —
// the user lands on the feed regardless of where it sits in source
// order.

enum WatchSurface: Hashable {
    case feed
    case tapestry
    case account
}

struct RootView: View {
    @EnvironmentObject var auth: AuthState
    @State private var selection: WatchSurface = .feed

    var body: some View {
        if auth.credentials == nil {
            EmptyAuthView()
        } else {
            TabView(selection: $selection) {
                Tab(value: WatchSurface.account) {
                    AccountView()
                }
                if auth.supportsTapestry {
                    Tab(value: WatchSurface.tapestry) {
                        TapestryFeedView()
                    }
                }
                Tab(value: WatchSurface.feed) {
                    MediaFeedView()
                }
            }
            .tabViewStyle(.verticalPage)
            .onChange(of: auth.supportsTapestry) { _, supports in
                // Cross-account-switch defence: if the user happens to
                // be sitting on Tapestry when an account switch lands
                // on a non-supporting server, snap back to feed before
                // SwiftUI's value-keyed selection lands on whatever
                // tab happens to share an ordinal index.
                if !supports && selection == .tapestry {
                    selection = .feed
                }
            }
            .onReceive(NotificationCenter.default.publisher(for: .halflightOpenFeed)) { _ in
                // Latest Media complication tap → snap to the feed
                // surface. Source-order independent because the value-
                // keyed Tab API picks the matching tab regardless of
                // position. Emitted by `WatchAppDelegate.handle(_:)`
                // and the SwiftUI `.onContinueUserActivity` /
                // `.onOpenURL` hooks in `HalflightWatchApp` —
                // belt-and-suspenders for the watchOS NSUserActivity
                // delivery (Apple's docs are ambiguous about which
                // hook fires for `widgetURL` taps on which OS
                // revision, so we wire all three and let whichever
                // one runs land us on Feed).
                if selection != .feed { selection = .feed }
            }
        }
    }
}
