import UIKit

/// Lightweight Telegram-style popup menu for the gallery "..." button.
/// Reuses `TelegramContextMenuCardView` for the card visual and `TelegramContextMenuItem` for data.
/// No snapshot/blur overlay — the gallery is already dark.
final class GalleryMenuPopup: UIView {

    // MARK: - Constants

    private static let menuItemHeight: CGFloat = 44
    private static let menuGap: CGFloat = 8

    // MARK: - Subviews

    private let menuCard: TelegramContextMenuCardView

    // MARK: - State

    private let anchorFrame: CGRect
    private var isDismissing = false
    private var onDismiss: (() -> Void)?

    // MARK: - Init

    private init(items: [TelegramContextMenuItem], anchorFrame: CGRect, onDismiss: (() -> Void)?) {
        self.anchorFrame = anchorFrame
        self.onDismiss = onDismiss
        self.menuCard = TelegramContextMenuCardView(items: items, showSeparators: false, layoutStyle: .iconLeft)
        super.init(frame: .zero)
        buildHierarchy()
    }

    @available(*, unavailable)
    required init?(coder: NSCoder) { fatalError() }

    // MARK: - Public API

    @MainActor
    static func present(
        in container: UIView,
        anchorFrame: CGRect,
        items: [TelegramContextMenuItem],
        onDismiss: (() -> Void)? = nil
    ) {
        guard !items.isEmpty else { return }

        let popup = GalleryMenuPopup(items: items, anchorFrame: anchorFrame, onDismiss: onDismiss)
        popup.frame = container.bounds
        popup.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        container.addSubview(popup)
        popup.performPresentation()
    }

    // MARK: - Build

    private func buildHierarchy() {
        // No dim overlay — gallery is already dark, and dim blocks blur effect.
        // Tap-to-dismiss handled by gesture recognizer on self (transparent background).
        backgroundColor = .clear

        menuCard.layer.shadowColor = UIColor.black.cgColor
        menuCard.layer.shadowOpacity = 0.2
        menuCard.layer.shadowRadius = 10
        menuCard.layer.shadowOffset = CGSize(width: 0, height: 5)
        menuCard.onItemSelected = { [weak self] in
            self?.performDismissal()
        }
        addSubview(menuCard)

        let tap = UITapGestureRecognizer(target: self, action: #selector(tapDismiss(_:)))
        tap.delegate = self
        addGestureRecognizer(tap)
    }

    // MARK: - Layout

    private func layoutMenu() {
        let menuW = menuCard.preferredWidth
        let menuH = CGFloat(menuCard.itemCount) * Self.menuItemHeight
        let gap = Self.menuGap

        // Horizontal: right-align with anchor button
        let menuX = max(anchorFrame.maxX - menuW, 8)

        // Vertical: prefer below, fallback above
        let safeBottom = safeAreaInsets.bottom > 0 ? safeAreaInsets.bottom : 20
        let belowSpace = bounds.height - safeBottom - anchorFrame.maxY
        let menuAbove: Bool
        let menuY: CGFloat

        if belowSpace >= menuH + gap {
            menuY = anchorFrame.maxY + gap
            menuAbove = false
        } else {
            menuY = anchorFrame.minY - gap - menuH
            menuAbove = true
        }

        menuCard.frame = CGRect(x: menuX, y: menuY, width: menuW, height: menuH)

        // Anchor for scale: top-right (near "..." button)
        let anchorX: CGFloat = 1.0
        let anchorY: CGFloat = menuAbove ? 1.0 : 0.0
        setAnchorPointPreservingPosition(CGPoint(x: anchorX, y: anchorY), for: menuCard)
    }

    private func setAnchorPointPreservingPosition(_ anchor: CGPoint, for target: UIView) {
        let oldAnchor = target.layer.anchorPoint
        let delta = CGPoint(
            x: (anchor.x - oldAnchor.x) * target.bounds.width,
            y: (anchor.y - oldAnchor.y) * target.bounds.height
        )
        target.layer.anchorPoint = anchor
        target.layer.position = CGPoint(
            x: target.layer.position.x + delta.x,
            y: target.layer.position.y + delta.y
        )
    }

    // MARK: - Presentation

    private func performPresentation() {
        layoutMenu()

        menuCard.alpha = 0
        menuCard.transform = CGAffineTransform(scaleX: 0.01, y: 0.01)

        let spring = UISpringTimingParameters(
            mass: 5.0, stiffness: 900.0, damping: 88.0, initialVelocity: .zero
        )
        let animator = UIViewPropertyAnimator(duration: 0, timingParameters: spring)
        animator.addAnimations {
            self.menuCard.alpha = 1
            self.menuCard.transform = .identity
        }
        animator.startAnimation()
    }

    // MARK: - Dismissal

    private func performDismissal() {
        guard !isDismissing else { return }
        isDismissing = true

        UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseIn) {
            self.menuCard.alpha = 0
            self.menuCard.transform = CGAffineTransform(scaleX: 0.01, y: 0.01)
        } completion: { [weak self] _ in
            self?.onDismiss?()
            self?.removeFromSuperview()
        }
    }

    // MARK: - Gestures

    @objc private func tapDismiss(_ g: UITapGestureRecognizer) {
        performDismissal()
    }
}

// MARK: - UIGestureRecognizerDelegate

extension GalleryMenuPopup: UIGestureRecognizerDelegate {
    func gestureRecognizer(_ g: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
        guard g is UITapGestureRecognizer else { return true }
        let loc = touch.location(in: self)
        return !menuCard.frame.contains(loc)
    }
}
