import SwiftUI

public struct ScrollOffsetModifier: ViewModifier {
    let coordinateSpace: String
    let isHorizontal: Bool
    let onOffsetChange: (CGFloat) -> Void

    public func body(content: Content) -> some View {
        content
            .overlay {
                GeometryReader { geo in
                    if isHorizontal {
                        Color.clear
                            .preference(
                                key: HorizontalScrollOffsetPreferenceKey.self,
                                value: Double(-geo.frame(in: .named(coordinateSpace)).minX)
                            )
                    } else {
                        Color.clear
                            .preference(
                                key: VerticalScrollOffsetPreferenceKey.self,
                                value: Double(-geo.frame(in: .named(coordinateSpace)).minY)
                            )
                    }
                }
                .allowsHitTesting(false)
            }
            .onPreferenceChange(HorizontalScrollOffsetPreferenceKey.self) { offset in
                guard isHorizontal else { return }
                onOffsetChange(CGFloat(offset))
            }
            .onPreferenceChange(VerticalScrollOffsetPreferenceKey.self) { offset in
                guard !isHorizontal else { return }
                onOffsetChange(CGFloat(offset))
            }
    }
}

public extension View {
    /// Tracks scroll offset in the given coordinate space.
    /// - Parameters:
    ///   - coordinateSpace: Coordinate space name (default: "global")
    ///   - isHorizontal: Track horizontal (true) or vertical (false) scroll
    ///   - onOffsetChange: Called whenever the offset changes
    func trackScrollOffset(
        coordinateSpace: String = "global",
        isHorizontal: Bool = true,
        onOffsetChange: @escaping (CGFloat) -> Void
    ) -> some View {
        self.modifier(ScrollOffsetModifier(
            coordinateSpace: coordinateSpace,
            isHorizontal: isHorizontal,
            onOffsetChange: onOffsetChange
        ))
    }
}
