import SwiftUI

// MARK: - Detent Definition
enum CustomSheetDetent: Equatable, Hashable {
    case custom(CGFloat)
    case half
    case full
    case flex // Height based on content

    func height(screenHeight: CGFloat, contentHeight: CGFloat? = nil) -> CGFloat {
        switch self {
        case .custom(let height):
            return height
        case .half:
            return screenHeight * 0.5
        case .full:
            return screenHeight
        case .flex:
            // Use content height if available, otherwise use half screen as fallback
            guard let contentHeight = contentHeight, contentHeight > 0 else {
                return screenHeight * 0.5
            }
            // Clamp between min (100) and max (screen height - 50)
            return min(max(contentHeight, 100), screenHeight - 50)
        }
    }
}

// MARK: - Sheet Style
enum CustomSheetStyle {
    case edgeToEdge  // Ignore safe area, full width
    case floating    // 16px padding around sheet like a card
}

// MARK: - Sheet Background
enum CustomSheetBackground {
    case solid(Color)
    case glass
}

// MARK: - Custom Sheet View
struct CustomSheet<Content: View, AboveSheetContent: View>: View {
    @Binding var isPresented: Bool
    @Binding var currentDetent: CustomSheetDetent
    let detents: [CustomSheetDetent]
    let style: CustomSheetStyle
    let background: CustomSheetBackground
    let allowsFullDismissal: Bool
    let showDimmedBackground: Bool
    let showGrabber: Bool
    var sheetHeight: Binding<CGFloat>? // Optional binding to report sheet height
    let content: Content
    let aboveSheetContent: AboveSheetContent?

    // Drag state
    @State private var dragOffset: CGFloat = 0
    @State private var lastDragValue: CGFloat = 0
    @GestureState private var dragState: DragState = .inactive
    @State private var isDragging: Bool = false
    @State private var dragStartHeight: CGFloat = 0
    @State private var dragStartDetent: CustomSheetDetent = .flex
    @State private var dragMaxHeight: CGFloat = 0
    @State private var dragStartedAtTop: Bool = false

    // Keyboard tracking
    @State private var keyboardHeight: CGFloat = 0

    // Animation state
    @State private var animatedOffset: CGFloat = 0

    // Content height tracking
    @State private var contentHeight: CGFloat = 0

    // Scroll tracking for ScrollView support
    @State private var scrollOffset: CGFloat = 0
    @State private var isScrollViewAtTop: Bool = true
    @State private var isSheetDraggingDown: Bool = false

    init(
        isPresented: Binding<Bool>,
        currentDetent: Binding<CustomSheetDetent>,
        detents: [CustomSheetDetent],
        style: CustomSheetStyle = .edgeToEdge,
        background: CustomSheetBackground = .solid(Color(red: 0x1C/255.0, green: 0x1C/255.0, blue: 0x1F/255.0).opacity(0.95)),
        allowsFullDismissal: Bool = false,
        showDimmedBackground: Bool = false,
        showGrabber: Bool = true,
        sheetHeight: Binding<CGFloat>? = nil,
        @ViewBuilder content: () -> Content,
        @ViewBuilder aboveSheetContent: () -> AboveSheetContent
    ) {
        self._isPresented = isPresented
        self._currentDetent = currentDetent
        self.detents = detents
        self.style = style
        self.background = background
        self.allowsFullDismissal = allowsFullDismissal
        self.showDimmedBackground = showDimmedBackground
        self.showGrabber = showGrabber
        self.sheetHeight = sheetHeight
        self.content = content()
        self.aboveSheetContent = aboveSheetContent()
    }

    var body: some View {
        GeometryReader { geometry in
            ZStack(alignment: .bottom) {
                // Dimmed background (optional)
                if showDimmedBackground {
                    if isPresented {
                        Color.black.opacity(0.4)
                            .ignoresSafeArea()
                            .onTapGesture {
                                if allowsFullDismissal {
                                    dismissSheet()
                                } else {
                                    // Return to flex detent instead of dismissing
                                    withAnimation(.spring(response: 0.4, dampingFraction: 0.8)) {
                                        currentDetent = .flex
                                    }
                                }
                            }
                            .transition(.opacity)
                    }
                } else {
                    // When no dimmed background, add a clear spacer to maintain bottom alignment
                    Color.clear
                        .ignoresSafeArea()
                }

                // Sheet content with above-sheet content
                if isPresented {
                    VStack(spacing: 0) {
                        // Content above the sheet (only in flex mode)
                        if currentDetent == .flex, let aboveContent = aboveSheetContent {
                            aboveContent
                                .transition(.move(edge: .bottom).combined(with: .opacity))
                                .offset(y: totalOffset(in: geometry))
                        }

                        // Main sheet content
                        VStack(spacing: 0) {
                        // Grabber (optional, fades out when keyboard is visible)
                        if showGrabber {
                            VStack(spacing: 0) {
                                RoundedRectangle(cornerRadius: 100)
                                    .fill(Color.white.opacity(0.3))
                                    .frame(width: 36, height: 4)
                                    .padding(.vertical, 8)
                            }
                            .frame(maxWidth: .infinity)
                            .opacity(keyboardHeight > 0 ? 0 : 1)
                        }

                        content
                            .environment(\.customSheetScrollAtTop, isScrollViewAtTop)
                            .environment(\.customSheetDraggingDown, isSheetDraggingDown)
                            .id(currentDetent) // Force view identity to change with detent
                        }
                        .fixedSize(horizontal: false, vertical: currentDetent == .flex)
                    .ignoresSafeArea(edges: currentDetent == .full ? .bottom : [])
                    .background(
                        GeometryReader { contentGeometry in
                            Color.clear
                                .preference(key: ContentHeightKey.self, value: contentGeometry.size.height)
                        }
                    )
                    .onPreferenceChange(ContentHeightKey.self) { height in
                        if height > 0 && currentDetent == .flex && !isDragging {
                            contentHeight = height
                        }
                    }
                    .onPreferenceChange(ScrollOffsetPreferenceKey.self) { offset in
                        scrollOffset = offset
                        // Only consider at top if offset is negative or exactly 0
                        // Negative values can occur during bounce/overscroll at top
                        isScrollViewAtTop = offset <= 0
                    }
                    .frame(height: currentDetent == .flex ? nil : (isDragging ? dragStartHeight : sheetHeight(in: geometry)), alignment: .top)
                    .frame(maxWidth: .infinity)
                    .background {
                        Group {
                            switch background {
                            case .solid(let color):
                                RoundedRectangle(cornerRadius: cornerRadius)
                                    .fill(color)
                            case .glass:
                                RoundedRectangle(cornerRadius: cornerRadius)
                                    .fill(Constants.Colors.Background.secondary)
                                    .glassEffect(.regular.interactive(), in: RoundedRectangle(cornerRadius: cornerRadius))
                            }
                        }
                    }
                    .clipShape(RoundedRectangle(cornerRadius: cornerRadius))
                    .padding(style == .floating && (isDragging ? dragStartDetent : currentDetent) != .full ? EdgeInsets(top: 0, leading: 16, bottom: 16, trailing: 16) : EdgeInsets())
                    .offset(y: totalOffset(in: geometry))
                    .simultaneousGesture(
                        DragGesture(minimumDistance: 10)
                            .onChanged { value in
                                handleDragChanged(value, in: geometry)
                            }
                            .onEnded { value in
                                handleDragEnded(value, in: geometry)
                            }
                    )
                    }
                    .transition(.move(edge: .bottom))
                }
            }
        }
        .ignoresSafeArea(edges: .bottom)
        .animation(isDragging ? nil : .spring(response: 0.4, dampingFraction: 0.8), value: isPresented)
        .animation(isDragging ? nil : .spring(response: 0.4, dampingFraction: 0.8), value: animatedOffset)
        .animation(isDragging ? nil : .spring(response: 0.4, dampingFraction: 0.8), value: currentDetent)
        .onChange(of: currentDetent) { oldDetent, newDetent in
            // When detent changes, assume we're at top
            // The ScrollView will immediately update this if not true
            scrollOffset = 0
            isScrollViewAtTop = true
        }
        .background(
            GeometryReader { geometry in
                Color.clear
                    .onAppear {
                        updateSheetHeight(geometry: geometry)
                    }
                    .onChange(of: currentDetent) { _, _ in
                        updateSheetHeight(geometry: geometry)
                    }
                    .onChange(of: contentHeight) { _, _ in
                        updateSheetHeight(geometry: geometry)
                    }
            }
        )
        .onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)) { notification in
            handleKeyboardShow(notification)
        }
        .onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillHideNotification)) { _ in
            handleKeyboardHide()
        }
        .onReceive(NotificationCenter.default.publisher(for: NSNotification.Name("CustomSheetScrollOffset"))) { notification in
            if let offset = notification.userInfo?["offset"] as? CGFloat {
                scrollOffset = offset
                isScrollViewAtTop = offset <= 0
            }
        }
    }

    // MARK: - Helper Functions

    private var cornerRadius: CGFloat {
        36
    }

    private func sheetHeight(in geometry: GeometryProxy) -> CGFloat {
        let screenHeight = geometry.size.height
        let safeAreaTop = geometry.safeAreaInsets.top
        let safeAreaBottom = geometry.safeAreaInsets.bottom

        if currentDetent == .full {
            // Full detent: fill from safe area top to physical bottom
            // Since we ignore bottom safe area, add it back to reach true bottom
            return screenHeight
        } else {
            // Other detents use calculated height without adjustment
            // The .ignoresSafeArea(edges: .bottom) handles bottom positioning
            return currentDetent.height(screenHeight: screenHeight, contentHeight: contentHeight)
        }
    }

    private func totalOffset(in geometry: GeometryProxy) -> CGFloat {
        var baseOffset = dragOffset + animatedOffset

        // When keyboard is visible and sheet is in flex mode, offset UP to sit on top of keyboard
        let keyboardOffset: CGFloat
        if keyboardHeight > 0 && currentDetent == .flex && !isDragging {
            keyboardOffset = -keyboardHeight
        } else {
            keyboardOffset = 0
        }

        // Apply resistance when dragging beyond bounds (but not for keyboard offset)
        if baseOffset < 0 {
            // Dragging up beyond full height - apply resistance
            return (baseOffset * 0.3) + keyboardOffset
        }

        return baseOffset + keyboardOffset
    }

    private func handleDragChanged(_ value: DragGesture.Value, in geometry: GeometryProxy) {
        // Disable dragging when keyboard is visible
        if keyboardHeight > 0 {
            return
        }

        let translation = value.translation.height
        let horizontalTranslation = abs(value.translation.width)
        let verticalTranslation = abs(value.translation.height)

        // Ignore gesture if it's primarily horizontal
        if horizontalTranslation > verticalTranslation {
            return
        }

        // Capture if drag started at top on first movement
        if !isDragging {
            dragStartedAtTop = isScrollViewAtTop
        }

        // Only process if drag started when ScrollView was at top
        if !dragStartedAtTop {
            isSheetDraggingDown = false
            return
        }

        // When at top of ScrollView, only handle downward drags
        // Let upward drags pass through to ScrollView
        if isScrollViewAtTop && translation < 0 {
            // Dragging up when at top - only handle if expanding sheet (not at full yet)
            if currentDetent == .full {
                isSheetDraggingDown = false
                return
            }
        }

        // Use transaction to disable implicit animations during drag
        var transaction = Transaction()
        transaction.disablesAnimations = true

        withTransaction(transaction) {
            // Capture the starting height and detent on first drag movement
            if !isDragging {
                isDragging = true
                dragStartHeight = sheetHeight(in: geometry)
                dragStartDetent = currentDetent
                // Cache max height to avoid recalculation during drag
                dragMaxHeight = detents.map { $0.height(screenHeight: geometry.size.height, contentHeight: contentHeight) }.max() ?? dragStartHeight
            }

            if translation < 0 {
                // Dragging up - expand sheet to full
                isSheetDraggingDown = false
                dragOffset = translation
            } else {
                // Dragging down - collapse sheet or dismiss, block ScrollView
                isSheetDraggingDown = true
                dragOffset = translation
            }
        }
    }

    private func handleDragEnded(_ value: DragGesture.Value, in geometry: GeometryProxy) {
        // Disable dragging when keyboard is visible
        if keyboardHeight > 0 {
            return
        }

        let translation = value.translation.height
        let velocity = value.predictedEndTranslation.height - translation

        // Reset drag state
        isDragging = false
        isSheetDraggingDown = false

        // Only process if drag started at top
        if !dragStartedAtTop {
            dragStartedAtTop = false
            return
        }

        dragStartedAtTop = false

        // Check for dismiss gesture - drag down more than 100pt or fast downward velocity
        if translation > 100 || velocity > 500 {
            if allowsFullDismissal {
                // Only fully dismiss if explicitly allowed
                dismissSheet()
                dragOffset = 0
                return
            } else {
                // Otherwise, return to flex detent
                withAnimation(.spring(response: 0.4, dampingFraction: 0.8)) {
                    currentDetent = .flex
                    dragOffset = 0
                }
                return
            }
        }

        // Find the closest detent based on drag direction and velocity
        let currentHeight = currentDetent.height(screenHeight: geometry.size.height, contentHeight: contentHeight)
        let sortedDetents = detents.sorted {
            $0.height(screenHeight: geometry.size.height, contentHeight: contentHeight) <
            $1.height(screenHeight: geometry.size.height, contentHeight: contentHeight)
        }

        var targetDetent = currentDetent
        if translation > 30 || velocity > 200 {
            // Dragging down - go to smaller detent
            if let nextDetent = sortedDetents.last(where: {
                $0.height(screenHeight: geometry.size.height, contentHeight: contentHeight) < currentHeight
            }) {
                targetDetent = nextDetent
            }
        } else if translation < -30 || velocity < -200 {
            // Dragging up - go to larger detent
            if let nextDetent = sortedDetents.first(where: {
                $0.height(screenHeight: geometry.size.height, contentHeight: contentHeight) > currentHeight
            }) {
                targetDetent = nextDetent
            }
        }

        // Apply detent change and reset drag offset together with animation
        withAnimation(.spring(response: 0.4, dampingFraction: 0.8)) {
            currentDetent = targetDetent
            dragOffset = 0
        }
    }

    private func dismissSheet() {
        withAnimation(.spring(response: 0.3, dampingFraction: 0.9)) {
            isPresented = false
        }
    }

    private func handleKeyboardShow(_ notification: Notification) {
        guard let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else {
            return
        }

        withAnimation(.easeOut(duration: 0.3)) {
            keyboardHeight = keyboardFrame.height
        }
    }

    private func handleKeyboardHide() {
        withAnimation(.easeOut(duration: 0.3)) {
            keyboardHeight = 0
        }
    }

    private func updateSheetHeight(geometry: GeometryProxy) {
        let calculatedHeight = currentDetent.height(screenHeight: geometry.size.height, contentHeight: contentHeight)
        // Add bottom padding if floating style and not full detent
        let bottomPadding: CGFloat = (style == .floating && currentDetent != .full) ? 16 : 0
        let totalHeight = calculatedHeight + bottomPadding
        sheetHeight?.wrappedValue = totalHeight
    }
}

// MARK: - Drag State
enum DragState {
    case inactive
    case dragging(translation: CGFloat, velocity: CGFloat)

    var translation: CGFloat {
        switch self {
        case .inactive:
            return 0
        case .dragging(let translation, _):
            return translation
        }
    }

    var velocity: CGFloat {
        switch self {
        case .inactive:
            return 0
        case .dragging(_, let velocity):
            return velocity
        }
    }
}

// MARK: - Preference Key for Content Height
struct ContentHeightKey: PreferenceKey {
    static var defaultValue: CGFloat = 0
    static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
        value = nextValue()
    }
}

// MARK: - Preference Key for Scroll Offset
struct ScrollOffsetPreferenceKey: PreferenceKey {
    static var defaultValue: CGFloat = 0
    static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
        value = nextValue()
    }
}

// MARK: - Environment Key for Scroll Position
private struct CustomSheetScrollAtTopKey: EnvironmentKey {
    static let defaultValue: Bool = true
}

extension EnvironmentValues {
    var customSheetScrollAtTop: Bool {
        get { self[CustomSheetScrollAtTopKey.self] }
        set { self[CustomSheetScrollAtTopKey.self] = newValue }
    }
}

// MARK: - Environment Key for Sheet Dragging Down
private struct CustomSheetDraggingDownKey: EnvironmentKey {
    static let defaultValue: Bool = false
}

extension EnvironmentValues {
    var customSheetDraggingDown: Bool {
        get { self[CustomSheetDraggingDownKey.self] }
        set { self[CustomSheetDraggingDownKey.self] = newValue }
    }
}

// MARK: - Convenience Initializer (No Above Sheet Content)
extension CustomSheet where AboveSheetContent == EmptyView {
    init(
        isPresented: Binding<Bool>,
        currentDetent: Binding<CustomSheetDetent>,
        detents: [CustomSheetDetent],
        style: CustomSheetStyle = .edgeToEdge,
        background: CustomSheetBackground = .solid(Color(red: 0x1C/255.0, green: 0x1C/255.0, blue: 0x1F/255.0).opacity(0.95)),
        allowsFullDismissal: Bool = false,
        showDimmedBackground: Bool = false,
        showGrabber: Bool = true,
        sheetHeight: Binding<CGFloat>? = nil,
        @ViewBuilder content: () -> Content
    ) {
        self.init(
            isPresented: isPresented,
            currentDetent: currentDetent,
            detents: detents,
            style: style,
            background: background,
            allowsFullDismissal: allowsFullDismissal,
            showDimmedBackground: showDimmedBackground,
            showGrabber: showGrabber,
            sheetHeight: sheetHeight,
            content: content,
            aboveSheetContent: { EmptyView() }
        )
    }
}

// MARK: - ScrollView Offset Tracking
extension View {
    func trackScrollOffset() -> some View {
        self.background(
            GeometryReader { geometry in
                let offset = -geometry.frame(in: .named("scroll")).minY
                Color.clear
                    .preference(
                        key: ScrollOffsetPreferenceKey.self,
                        value: offset
                    )
                    .onAppear {
                        // Send initial offset via notification
                        NotificationCenter.default.post(
                            name: NSNotification.Name("CustomSheetScrollOffset"),
                            object: nil,
                            userInfo: ["offset": offset]
                        )
                    }
                    .onChange(of: offset) { oldValue, newValue in
                        // Send offset updates via notification for immediate updates
                        NotificationCenter.default.post(
                            name: NSNotification.Name("CustomSheetScrollOffset"),
                            object: nil,
                            userInfo: ["offset": newValue]
                        )
                    }
            }
        )
    }
}

// MARK: - ScrollView with Sheet Support
struct ScrollViewWithSheetSupport<Content: View>: View {
    @Environment(\.customSheetScrollAtTop) private var isAtTop
    @Environment(\.customSheetDraggingDown) private var isDraggingDown
    let content: Content

    init(@ViewBuilder content: () -> Content) {
        self.content = content()
    }

    var body: some View {
        ScrollView {
            content
                .trackScrollOffset()
        }
        .coordinateSpace(name: "scroll")
        .scrollBounceBehavior(isAtTop ? .basedOnSize : .automatic)
        .scrollDisabled(isDraggingDown)
    }
}

// MARK: - Preview
#Preview {
    CustomSheetPreview()
}

struct CustomSheetPreview: View {
    @State private var isPresented = false
    @State private var currentDetent: CustomSheetDetent = .flex
    @State private var chatText = ""
    @State private var field1Text = ""
    @State private var field2Text = ""
    @State private var showMoreContent = false
    @State private var sheetStyle: CustomSheetStyle = .floating
    @State private var sheetBackground: CustomSheetBackground = .glass
    @State private var showScrollTestSheet = false
    @State private var scrollTestDetent: CustomSheetDetent = .full

    var body: some View {
        ZStack {
            // Main content
            VStack(spacing: 24){


                    Text("Sheet Examples")
                    .font(Constants.Typography.largeTitle)
                    .foregroundColor(Constants.Colors.Foreground.primary)

                    HStack(spacing: 12) {
                        LargeButton(
                            title: "Chat Sheet",
                            variant: .primary
                        ) {
                            isPresented = true
                        }

                        LargeButton(
                            title: "Content Sheet",
                            variant: .primary
                        ) {
                            showScrollTestSheet = true
                        }
                    }

                    Divider()
                    
                    
                    Text("Options")
                    .font(Constants.Typography.largeTitle)
                    .foregroundColor(Constants.Colors.Foreground.primary)
                    
                    HStack(spacing: 12) {
                        Text("Style:")
                            .font(Constants.Typography.mediumTitle)
                            .foregroundColor(Constants.Colors.Foreground.primary)

                        MediumButton(
                            title: "Floating",
                            variant: sheetStyle == .floating ? .primary : .tertiary
                        ) {
                            sheetStyle = .floating
                        }

                        MediumButton(
                            title: "Edge to Edge",
                            variant: sheetStyle == .edgeToEdge ? .primary : .tertiary
                        ) {
                            sheetStyle = .edgeToEdge
                        }
                    }
                    .frame(maxWidth: .infinity, alignment: .leading)

                    HStack(spacing: 12) {
                        Text("Background:")
                            .font(Constants.Typography.mediumTitle)
                            .foregroundColor(Constants.Colors.Foreground.primary)

                        MediumButton(
                            title: "Glass",
                            variant: backgroundIsGlass ? .primary : .tertiary
                        ) {
                            sheetBackground = .glass
                        }

                        MediumButton(
                            title: "Solid",
                            variant: !backgroundIsGlass ? .primary : .tertiary
                        ) {
                            sheetBackground = .solid(Color(red: 0x1C/255.0, green: 0x1C/255.0, blue: 0x1F/255.0).opacity(0.95))
                        }
                    }
                    .frame(maxWidth: .infinity, alignment: .leading)
                
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
            .padding(24)
            .background(Constants.Colors.Background.primary)

            // Chat Sheet
            CustomSheet(
                isPresented: $isPresented,
                currentDetent: $currentDetent,
                detents: [.flex, .full],
                style: sheetStyle,
                background: sheetBackground
            ) {
                if currentDetent == .full {
                    // Full view with ScrollView and two multiline text fields
                    ScrollViewWithSheetSupport {
                        VStack(spacing: 16) {
                            Text("Advanced options")
                                .font(.title)
                                .foregroundColor(.white)

                            VStack(alignment: .leading, spacing: 8) {
                                Text("Field 1")
                                    .font(.headline)
                                    .foregroundColor(.white)
                                TextEditor(text: $field1Text)
                                    .frame(height: 400)
                                    .padding(8)
                                    .background(Color.white.opacity(0.1))
                                    .cornerRadius(8)
                                    .foregroundColor(.white)
                            }

                            VStack(alignment: .leading, spacing: 8) {
                                Text("Field 2")
                                    .font(.headline)
                                    .foregroundColor(.white)
                                TextEditor(text: $field2Text)
                                    .frame(height: 400)
                                    .padding(8)
                                    .background(Color.white.opacity(0.1))
                                    .cornerRadius(8)
                                    .foregroundColor(.white)
                            }

                            Spacer()
                                .frame(height: 40)
                        }
                        .padding(.horizontal, 20)
                    }
                } else {
                    // Flex view with text input and send button
                    HStack(spacing: 12) {
                        TextField("Let's chat", text: $chatText)
                            .textFieldStyle(PlainTextFieldStyle())
                            .padding()
                            .background(Color.white.opacity(0.1))
                            .cornerRadius(100)
                            .foregroundColor(.white)

                        Button(action: {
                            print("Send: \(chatText)")
                            chatText = ""
                        }) {
                            Image(systemName: "arrow.up.circle.fill")
                                .resizable()
                                .frame(width: 32, height: 32)
                                .foregroundColor(.blue)
                        }
                    }
                    .padding(.horizontal, 16)
                    .padding(.bottom, 16)
                }
            }

            // ScrollView Test Sheet
            CustomSheet(
                isPresented: $showScrollTestSheet,
                currentDetent: $scrollTestDetent,
                detents: [.full],
                style: .floating,
                background: .glass,
                allowsFullDismissal: true
            ) {
                ScrollViewWithSheetSupport {
                    VStack(spacing: 16) {
                        Text("ScrollView Test Sheet")
                            .font(.title)
                            .foregroundColor(.white)

                        Text("Full Detent Only - Test Scroll Behavior")
                            .font(.subheadline)
                            .foregroundColor(.white.opacity(0.7))
                            .multilineTextAlignment(.center)

                        VStack(alignment: .leading, spacing: 12) {
                            Text("Paragraph 1")
                                .font(.headline)
                                .foregroundColor(.white)
                            Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")
                                .foregroundColor(.white.opacity(0.8))
                                .lineSpacing(4)
                        }
                        .padding()
                        .background(Color.white.opacity(0.05))
                        .cornerRadius(12)

                        VStack(alignment: .leading, spacing: 12) {
                            Text("Paragraph 2")
                                .font(.headline)
                                .foregroundColor(.white)
                            Text("Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.")
                                .foregroundColor(.white.opacity(0.8))
                                .lineSpacing(4)
                        }
                        .padding()
                        .background(Color.white.opacity(0.05))
                        .cornerRadius(12)

                        VStack(alignment: .leading, spacing: 12) {
                            Text("Paragraph 3")
                                .font(.headline)
                                .foregroundColor(.white)
                            Text("But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure.")
                                .foregroundColor(.white.opacity(0.8))
                                .lineSpacing(4)
                        }
                        .padding()
                        .background(Color.white.opacity(0.05))
                        .cornerRadius(12)

                        VStack(alignment: .leading, spacing: 12) {
                            Text("Paragraph 4")
                                .font(.headline)
                                .foregroundColor(.white)
                            Text("At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio.")
                                .foregroundColor(.white.opacity(0.8))
                                .lineSpacing(4)
                        }
                        .padding()
                        .background(Color.white.opacity(0.05))
                        .cornerRadius(12)

                        Spacer()
                            .frame(height: 40)
                    }
                    .padding(.horizontal, 20)
                    .trackScrollOffset()
                }
                .coordinateSpace(name: "scroll")
            }
        }
    }

    private var detentName: String {
        switch currentDetent {
        case .custom(let height):
            return "Custom (\(Int(height))pt)"
        case .half:
            return "Half"
        case .full:
            return "Full"
        case .flex:
            return "Flex (Content-based)"
        }
    }

    private var backgroundIsGlass: Bool {
        if case .glass = sheetBackground {
            return true
        }
        return false
    }
}
