import SwiftUI

// MARK: - TourTargetPreferenceKey

/// Collects Anchor<CGRect> values for each registered TourTargetID.
struct TourTargetPreferenceKey: PreferenceKey {
    static var defaultValue: [TourTargetID: Anchor<CGRect>] = [:]

    static func reduce(
        value: inout [TourTargetID: Anchor<CGRect>],
        nextValue: () -> [TourTargetID: Anchor<CGRect>]
    ) {
        value.merge(nextValue()) { _, new in new }
    }
}

// MARK: - View Modifiers

extension View {

    /// Marks this view as a spotlightable tour target.
    /// The frame is collected via a preference key and forwarded to TourCoordinator.
    func tourTarget(_ id: TourTargetID) -> some View {
        anchorPreference(key: TourTargetPreferenceKey.self, value: .bounds) { anchor in
            [id: anchor]
        }
    }

    /// Conditional variant — applies `tourTarget` only when `id` is non-nil.
    /// Use `index == 0 ? .someTarget : nil` patterns for list-based targets.
    @ViewBuilder
    func tourTarget(_ id: TourTargetID?) -> some View {
        if let id {
            tourTarget(id)
        } else {
            self
        }
    }

    /// Adds the tour overlay to this view. Place at the root of a view hierarchy
    /// (ContentView for main-app tours, OnboardingContainerView for onboarding).
    ///
    /// - Parameter coordinator: The shared TourCoordinator instance.
    func tourPresenter(coordinator: TourCoordinator) -> some View {
        overlayPreferenceValue(TourTargetPreferenceKey.self) { anchors in
            GeometryReader { geo in
                // Convert preference anchors to CGRect in this coordinate space
                let frames: [TourTargetID: CGRect] = anchors.reduce(into: [:]) { result, pair in
                    result[pair.key] = geo[pair.value]
                }
                TourOverlayView(coordinator: coordinator, targetFrames: frames)
                    .frame(width: geo.size.width, height: geo.size.height)
            }
            .ignoresSafeArea()
        }
    }
}
