import SwiftUI
import UIKit

/// Transparent overlay that triggers a Telegram-style context menu on long press.
///
/// Also supports single-tap routing (image viewer, file download, reply quote tap)
/// because the overlay UIView intercepts all touch events, preventing SwiftUI
/// `onTapGesture` on content below from firing.
struct BubbleContextMenuOverlay: UIViewRepresentable {
    let items: [TelegramContextMenuItem]
    let previewShape: MessageBubbleShape
    let isOutgoing: Bool

    /// Called when user single-taps the bubble. Receives tap location in the overlay's
    /// coordinate space (for determining which sub-element was tapped, e.g., which photo in a collage)
    /// and the overlay UIView (for converting sub-rects to global coordinates).
    var onTap: ((CGPoint, UIView?) -> Void)?

    /// Height of the reply quote area at the top of the bubble (0 = no reply quote).
    /// Taps within this region call `onReplyQuoteTap` instead of `onTap`.
    var replyQuoteHeight: CGFloat = 0

    /// Called when user taps the reply quote area at the top of the bubble.
    var onReplyQuoteTap: (() -> Void)?

    func makeUIView(context: Context) -> UIView {
        let view = UIView()
        view.backgroundColor = .clear

        // Single tap recognizer — coexists with long press.
        // ALL taps go through this (overlay UIView blocks SwiftUI gestures below).
        let tap = UITapGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.handleTap(_:)))
        view.addGestureRecognizer(tap)

        // Long press → Telegram context menu
        let longPress = UILongPressGestureRecognizer(
            target: context.coordinator,
            action: #selector(Coordinator.handleLongPress(_:))
        )
        longPress.minimumPressDuration = 0.35
        view.addGestureRecognizer(longPress)

        return view
    }

    func updateUIView(_ uiView: UIView, context: Context) {
        context.coordinator.items = items
        context.coordinator.previewShape = previewShape
        context.coordinator.isOutgoing = isOutgoing
        context.coordinator.onTap = onTap
        context.coordinator.replyQuoteHeight = replyQuoteHeight
        context.coordinator.onReplyQuoteTap = onReplyQuoteTap
    }

    func makeCoordinator() -> Coordinator { Coordinator(overlay: self) }

    final class Coordinator: NSObject {
        var items: [TelegramContextMenuItem]
        var previewShape: MessageBubbleShape
        var isOutgoing: Bool
        var onTap: ((CGPoint, UIView?) -> Void)?
        var replyQuoteHeight: CGFloat = 0
        var onReplyQuoteTap: (() -> Void)?
        private let haptic = UIImpactFeedbackGenerator(style: .medium)

        init(overlay: BubbleContextMenuOverlay) {
            self.items = overlay.items
            self.previewShape = overlay.previewShape
            self.isOutgoing = overlay.isOutgoing
            self.onTap = overlay.onTap
            self.replyQuoteHeight = overlay.replyQuoteHeight
            self.onReplyQuoteTap = overlay.onReplyQuoteTap
        }

        // MARK: - Single Tap

        @objc func handleTap(_ recognizer: UITapGestureRecognizer) {
            // Route taps in the reply quote region to the reply handler.
            if replyQuoteHeight > 0, let view = recognizer.view {
                let location = recognizer.location(in: view)
                if location.y < replyQuoteHeight {
                    onReplyQuoteTap?()
                    return
                }
            }
            let location = recognizer.location(in: recognizer.view)
            onTap?(location, recognizer.view)
        }

        // MARK: - Long Press → Context Menu

        @objc func handleLongPress(_ recognizer: UILongPressGestureRecognizer) {
            guard recognizer.state == .began else { return }
            haptic.impactOccurred()
            presentMenu(from: recognizer.view)
        }

        private func presentMenu(from view: UIView?) {
            guard let view else { return }
            guard !items.isEmpty else { return }

            // Capture snapshot from window
            guard let (snapshot, frame) = TelegramContextMenuController.captureSnapshot(of: view) else { return }

            // Build bubble mask path
            let shapePath = previewShape.path(in: CGRect(origin: .zero, size: frame.size))
            let bubblePath = UIBezierPath(cgPath: shapePath.cgPath)

            TelegramContextMenuController.present(
                snapshot: snapshot,
                sourceFrame: frame,
                bubblePath: bubblePath,
                items: items,
                isOutgoing: isOutgoing
            )
        }
    }
}
