import SwiftUI

// import SwiftUIIntrospect
import UIKit

struct SpotifyPlayer: View {
    enum k {
        static let tabBarHeight = 85.0
    }

    @State var isExpanded = false

    @State var collapsedSize = CGSize.zero
    @State var viewSize = CGSize.zero

    @State private var dragOffset: CGFloat = 0
    @State private var horizontalDragOffset: CGFloat = 0

    var expandedOpacity: Double {
        if isExpanded {
            return 1
        } else {
            return abs(dragOffset) / 100.0
        }
    }

    var collapsedOpacity: Double {
        if isExpanded {
            return 0
        } else {
            return abs(dragOffset) < 10 ? 1 : 0
        }
    }

    var body: some View {
        ZStack {
            interactiveTransitionBody

            DemoTabBar()
        }
    }

    @ViewBuilder var interactiveTransitionBody: some View {
        ZStack {
            Expanded(
                dragChanged: { value in
                    if abs(value.translation.width) > abs(value.translation.height) {
                        horizontalDragOffset = value.translation.width
                        dragOffset = 0
                    } else {
                        dragOffset = max(0, value.translation.height)
                        horizontalDragOffset = 0
                    }
                },
                dragEnded: { value in
                    if abs(value.translation.width) > abs(value.translation.height) {
                        withAnimation(.spring(duration: 0.2)) {
                            if abs(value.translation.width) > 100 {
                                isExpanded = false
                            }
                            horizontalDragOffset = 0
                        }
                    } else {
                        withAnimation(.spring(duration: 0.2)) {
                            if value.translation.height > 100 {
                                isExpanded = false
                            }
                            dragOffset = 0
                        }
                    }
                }
            )
            .ignoresSafeArea()
//                .clipShape(RoundedRectangle(cornerSize: CGSize(width: 24, height: 24)))
            .opacity(expandedOpacity)
            .offset(x: isExpanded ? horizontalDragOffset : 0)
            VStack {
                Collapsed()
                    .onTapGesture {
                        withAnimation((.spring(duration: 0.2))) {
                            isExpanded = true
                        }
                    }
                    .opacity(collapsedOpacity)
                    .readSize(to: $collapsedSize)

                Spacer()
            }
        }
        .ignoresSafeArea()
        .offset(y: dragOffset)
        .offset(y: isExpanded ? 0 : viewSize.height - k.tabBarHeight)
//        .gesture(
//            DragGesture()
//                .onChanged { value in
//                    if isExpanded {
//                        if abs(value.translation.width) > abs(value.translation.height) {
//                            horizontalDragOffset = value.translation.width
//                            dragOffset = 0
//                        } else {
//                            dragOffset = max(0, value.translation.height)
//                            horizontalDragOffset = 0
//                        }
//                    } else {
//                        dragOffset = min(0, value.translation.height)
//                    }
//                }
//                .onEnded { value in
//                    if isExpanded {
//                        withAnimation(.spring(duration: 0.2)) {
//                            if abs(value.translation.width) > abs(value.translation.height) {
//                                if abs(value.translation.width) > 100 {
//                                    horizontalDragOffset = 0
//                                    isExpanded = false
//                                } else {
//                                    horizontalDragOffset = 0
//                                }
//                            } else {
//                                if value.translation.height > 100 {
//                                    dragOffset = 0
//                                    isExpanded = false
//                                } else {
//                                    dragOffset = 0
//                                }
//                            }
//                        }
//                    } else {
//                        withAnimation(.spring(duration: 0.2)) {
//                            if value.translation.height < -100 {
//                                dragOffset = 0
//                                isExpanded = true
//                            } else {
//                                dragOffset = 0
//                            }
//                        }
//                    }
//                }
//        )
        .ignoresSafeArea()
        .readSize(to: $viewSize)
    }

    @ViewBuilder var simpleTransitionBody: some View {
        if isExpanded {
            Expanded()
                .overlay {
                    Button(action: {
                        withAnimation {
                            isExpanded = false
                        }
                    }, label: {
                        Text("Close")
                            .foregroundStyle(.white)
                    })
                }

                .onTapGesture {
                    withAnimation {
                        isExpanded.toggle()
                    }
                }
                .transition(
                    .move(edge: .bottom)
//                    .asymmetric(insertion: , removal: .identity)
                )
        } else {
            Collapsed()
                .onTapGesture {
                    withAnimation {
                        isExpanded.toggle()
                    }
                }
                .offset(y: dragOffset)
                .gesture(
                    DragGesture()
//                        .updating($dragOffset) { value, state, _ in
//                            state = value.translation.height
//                        }
                            .onEnded { value in
                                print(value.translation.height)
                                if isExpanded {
                                } else {
                                    if value.translation.height < -100 {
                                        withAnimation {
                                            isExpanded = true
                                        }
                                    }
                                }
                            }
                )
        }
    }

    struct Collapsed: View {
        var body: some View {
            Rectangle()
                .foregroundStyle(.green)
                .frame(height: 80)
                .frame(maxWidth: .infinity)
                .overlay {
                    HStack {
                        Rectangle()
                            .aspectRatio(contentMode: .fit)
                            .foregroundStyle(.red)
                            .padding()
                            .overlay(
                                Image(systemName: "music.note")
                            )
                        VStack(alignment: .leading) {
                            Text("CHEEZY STREET")
                                .font(.title3)
                            Text("Louie Zhong")
                                .font(.caption)
                        }

                        Spacer()
                    }
                }
                .clipShape(RoundedRectangle(cornerRadius: 12))
                .padding(.horizontal, 12)
        }
    }

    struct Expanded: View {
        private let colors: [Color] = [.pink, .yellow, .blue]
        var dragChanged: ((ScrollViewInteroperableDragGesture.Value) -> Void)? = nil
        var dragEnded: ((ScrollViewInteroperableDragGesture.Value) -> Void)? = nil

        @State private var startedInteroperableDrag = false

        var body: some View {
            scrollingBody
        }

        private var staticBody: some View {
            Rectangle()
                .foregroundStyle(.red)
        }

        @ViewBuilder private var scrollingBody: some View {
            ScrollView(showsIndicators: false) {
                LazyVStack(spacing: 0) {
                    ForEach(colors, id: \.self) { _ in
//                        ZStack {
                        Rectangle()
                            .foregroundStyle(.red)
                            .frame(height: 700)
                            .cornerRadius(12)
                            .padding(.horizontal, 12)
                            .padding(.top, -50)
                            .padding(.bottom, 50)
                            .overlay(
                                Image(systemName: "music.note")
                                    .foregroundColor(.white)
                            )
//                                .padding(.top, 12)
//                                .padding(.bottom, 8)
                            .ignoresSafeArea()
                    }
                }
                .ignoresSafeArea()
            }
            .ignoresSafeArea()
//            .introspect(.scrollView, on: .iOS(.v18)) { scrollView in
//                scrollView.backgroundColor = .yellow
//                scrollView.contentInsetAdjustmentBehavior = .never
//            }
            .gesture(ScrollViewInteroperableDragGesture(
                configuration: ScrollViewInteroperableDragGesture.Configuration(
                    ignoresScrollView: false,
                    targetEdges: .vertical,
                    sticksToEdges: true
                ),
                isScrollLockEnabled: $startedInteroperableDrag,
                coordinateSpaceInDragging: .global,
                onChange: { value in
                    self.dragChanged?(value)
                    startedInteroperableDrag = true
                },
                onEnd: { value in
                    self.dragEnded?(value)
                    startedInteroperableDrag = false
                }
            ))
        }
    }

    struct DemoTabBar: View {
        var body: some View {
            HStack {
                Spacer()
                VStack(spacing: 4) {
                    Image(systemName: "house.fill")
                        .font(.system(size: 24))
                    Text("Home")
                        .font(.caption)
                }
                Spacer()
                VStack(spacing: 4) {
                    Image(systemName: "magnifyingglass")
                        .font(.system(size: 24))
                    Text("Search")
                        .font(.caption)
                }
                Spacer()
                VStack(spacing: 4) {
                    Image(systemName: "books.vertical.fill")
                        .font(.system(size: 24))
                    Text("Library")
                        .font(.caption)
                }
                Spacer()
            }
            .foregroundColor(.white)
            .padding(.top, 10)
            .background(Color.black.opacity(0.9))
            .frame(maxHeight: .infinity, alignment: .bottom)
        }
    }

    struct ExpandingShape: Shape {
        let progress: CGFloat
        let startHeight: CGFloat
        let maxHeight: CGFloat

        func path(in rect: CGRect) -> Path {
            var path = Path()
            let height = startHeight + (maxHeight - startHeight) * progress
            path.addRoundedRect(in: CGRect(x: 0, y: 0, width: rect.width, height: height), cornerSize: CGSize(width: 12, height: 12))
            return path
        }
    }
}

#Preview {
    Rectangle()
        .foregroundStyle(.blue)
        .ignoresSafeArea()
        .overlay(alignment: .bottom) {
            SpotifyPlayer()
        }
        .onAppear {
            UIScrollView.appearance().bounces = false
            UIScrollView.appearance().contentInsetAdjustmentBehavior = .scrollableAxes
            UIScrollView.appearance().backgroundColor = .yellow
        }
}
