import SwiftUI
import UIKit

/// Displays text that shows a native iOS callout bubble ("Copy") on tap or long press.
/// Uses `UIEditMenuInteraction` for the system callout style.
struct CopyableText: UIViewRepresentable {
    let displayText: String
    let fullText: String
    let font: UIFont
    let textColor: UIColor

    func makeUIView(context: Context) -> CopyableLabel {
        let label = CopyableLabel()
        label.text = displayText
        label.font = font
        label.textColor = textColor
        label.textToCopy = fullText
        label.textAlignment = .center
        label.setContentHuggingPriority(.required, for: .vertical)
        label.setContentCompressionResistancePriority(.required, for: .vertical)
        return label
    }

    func updateUIView(_ uiView: CopyableLabel, context: Context) {
        uiView.text = displayText
        uiView.font = font
        uiView.textColor = textColor
        uiView.textToCopy = fullText
    }
}

/// UILabel subclass with `UIEditMenuInteraction` for native callout copy menu.
final class CopyableLabel: UILabel, UIEditMenuInteractionDelegate {

    var textToCopy: String = ""

    private var editMenuInteraction: UIEditMenuInteraction?

    override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }

    @available(*, unavailable)
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    private func setup() {
        isUserInteractionEnabled = true

        let interaction = UIEditMenuInteraction(delegate: self)
        addInteraction(interaction)
        editMenuInteraction = interaction

        let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
        addGestureRecognizer(tap)

        let longPress = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(_:)))
        longPress.minimumPressDuration = 0.5
        addGestureRecognizer(longPress)
    }

    @objc private func handleTap(_ gesture: UITapGestureRecognizer) {
        showMenu(at: gesture.location(in: self))
    }

    @objc private func handleLongPress(_ gesture: UILongPressGestureRecognizer) {
        guard gesture.state == .began else { return }
        showMenu(at: gesture.location(in: self))
    }

    private func showMenu(at point: CGPoint) {
        let config = UIEditMenuConfiguration(identifier: nil, sourcePoint: point)
        editMenuInteraction?.presentEditMenu(with: config)
    }

    // MARK: - UIEditMenuInteractionDelegate

    func editMenuInteraction(
        _ interaction: UIEditMenuInteraction,
        menuFor configuration: UIEditMenuConfiguration,
        suggestedActions: [UIMenuElement]
    ) -> UIMenu? {
        let textToCopy = textToCopy
        let copy = UIAction(
            title: String(localized: "Copy"),
            image: UIImage(systemName: "doc.on.doc")
        ) { _ in
            UIPasteboard.general.string = textToCopy
        }
        return UIMenu(children: [copy])
    }
}
