//
//  WorkspacesOverlay.swift
//  suno
//
//  Created by Sidney Sadel on 11/12/25.
//

import ComposableArchitecture
import SwiftUI
import UIKit

/// This view contains the workspace menu + background
/// + logic for expanding to full view on tap of text field button
struct WorkspacesOverlay: View {
    let store: StoreOf<OrpheusWorkspacesReducer>
    @Binding var isPresented: Bool
    
    @State private var dragXOffset: CGFloat = .zero
    
    var body: some View {
        GeometryReader { proxy in
            ZStack {
                if isPresented {
                    Color(red: 0, green: 0, blue: 0, opacity: 0.4)
                        .ignoresSafeArea()
                        .onTapGesture {
                            isPresented = false
                        }
                }
                
                if isPresented {
                    WorkspacesView(store: store, size: proxy.size)
                        .zIndex(1)
                        .offset(x: dragXOffset)
                        .transition(.move(edge: .leading))
                        .gesture(dragGesture(proxy: proxy))
                }
            }
            .animation(.smooth(duration: 0.35), value: isPresented)
            .onChange(of: isPresented) { _, newValue in
                if !newValue {
                    store.send(.searchQueryChanged(""))
                }
            }
        }
    }
    
    private func dragGesture(proxy: GeometryProxy) -> some UIGestureRecognizerRepresentable {
        let threshold = proxy.size.width * 0.3
        
        return HorizontalDismissGesture(
            offset: $dragXOffset,
            onEnded: { translation, isFastSwipe in
                let shouldDismiss = translation < -threshold || isFastSwipe
                
                withAnimation(.smooth(duration: 0.35)) {
                    dragXOffset = 0
                }
                
                if shouldDismiss {
                    isPresented = false
                    dismissKeyboard()
                }
            }
        )
    }
}

// MARK: - Gestures
fileprivate
struct HorizontalDismissGesture: UIGestureRecognizerRepresentable {
    @Binding var offset: CGFloat
    var onEnded: (CGFloat, Bool) -> Void
    
    func makeUIGestureRecognizer(context: Context) -> UIPanGestureRecognizer {
        let gesture = UIPanGestureRecognizer()
        gesture.delegate = context.coordinator
        return gesture
    }
    
    func handleUIGestureRecognizerAction(
        _ recognizer: UIPanGestureRecognizer,
        context: Context
    ) {
        let translation = recognizer.translation(in: recognizer.view).x
        let velocity = recognizer.velocity(in: recognizer.view)
        
        switch recognizer.state {
        case .began:
            context.coordinator.initialTranslation = recognizer.translation(in: recognizer.view)
        case .changed:
            offset = min(0, translation)
        case .ended, .cancelled:
            let isFastSwipe = velocity.x < -150
            onEnded(translation, isFastSwipe)
        default:
            break
        }
    }
    
    func makeCoordinator(converter: CoordinateSpaceConverter) -> Coordinator {
        Coordinator()
    }
    
    class Coordinator: NSObject, UIGestureRecognizerDelegate {
        var initialTranslation: CGPoint = .zero
        
        func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
            guard let pan = gestureRecognizer as? UIPanGestureRecognizer else { return true }
            let translation = pan.translation(in: pan.view)
            
            /// Only begin if horizontal movement is greater than vertical and moving to left (negative x)
            let isHorizontal = abs(translation.x) > abs(translation.y)
            let isMovingLeft = translation.x < 0
            
            return isHorizontal && isMovingLeft
        }
        
        func gestureRecognizer(
            _ gestureRecognizer: UIGestureRecognizer,
            shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer
        ) -> Bool {
            /// Don't allow simultaneous recognition - we want to block the ScrollView when this should be active
            return false
        }
    }
}

// MARK: - Previews
#Preview {
    @Previewable @State var isPresented: Bool = true
    ZStack {
        Button("Toggle") {
            isPresented.toggle()
        }
        
        WorkspacesOverlay(
            store: Store(initialState: OrpheusWorkspacesReducer.State()) {
                OrpheusWorkspacesReducer()
            } withDependencies: {
                $0.workspacesClient = .previewValue
            },
            isPresented: $isPresented
        )
    }
    .preferredColorScheme(.dark)
}
