//
//  YHFloatingWindow.swift
//  galaxy
//
//  Created by alexzzw on 2024/11/29.
//  Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//

import AgoraRtcKit
import UIKit

// MARK: - 浮窗管理

protocol YHFloatingWindowDelegate: AnyObject {
    func floatingWindowDidTap(_ window: YHFloatingWindow)
    func floatingWindowDidClose(_ window: YHFloatingWindow)
    func floatingWindow(_ window: YHFloatingWindow, didChangeSize size: CGSize)
    func floatingWindow(_ window: YHFloatingWindow, didChangePosition point: CGPoint)
}

class YHFloatingWindow: NSObject {
    // MARK: - Properties
    
    enum Source {
        case configured // 配置产生的小窗（只在推荐页显示）
        case userAction // 用户操作产生的小窗（全局显示）
    }

    weak var player: YHPlayer?
    var source: Source = .userAction
    
    weak var delegate: YHFloatingWindowDelegate?
    var playbackInfo: YHPlayerManager.PlaybackInfo? {
        didSet {
            if playbackInfo?.isLive == true {
                bottomView.isHidden = false
                bottomView.play(true)
            } else {
                bottomView.isHidden = true
                bottomView.play(false)
            }
        }
    }

    // 视频方向
    enum VideoOrientation {
        case portrait // 竖屏 9:16
        case landscape // 横屏 16:9

        var aspectRatio: CGFloat {
            switch self {
            case .portrait: return 9.0 / 16.0
            case .landscape: return 16.0 / 9.0
            }
        }
    }

    // 窗口尺寸
    private struct Size {
        static let minWidth: CGFloat = 120
        static let maxWidth: CGFloat = UIScreen.main.bounds.width
        static let minHeight: CGFloat = 67.5 // 16:9
        static let maxHeight: CGFloat = UIScreen.main.bounds.height

        static let defaultWidth: CGFloat = 72// 150
        static let defaultHeight: CGFloat = 128// 84.375 // 16:9
    }

    private(set) var contentView: UIView
    private var containerView: UIView
    private var videoOrientation: VideoOrientation = .portrait// .landscape

    // 手势相关
    private var initialFrame: CGRect = .zero
    private var isResizing: Bool = false
    private var initialCenter: CGPoint = .zero

    // 缩放相关
    private var currentScale: CGFloat = 1.0
    private var initialDistance: CGFloat = 0
    private let scaleMultiplier: CGFloat = 1.5
        
    var isHidden: Bool = false {
        didSet {
            contentView.isHidden = isHidden
            if isHidden {
                player?.isMuted = true
            } else {
                if source == .configured {
                    player?.isMuted = true
                } else {
                    player?.isMuted = false
                }
            }
        }
    }

    // UI组件
    private lazy var closeButton: UIButton = {
        let button = UIButton(type: .custom)
        button.setImage(UIImage(named: "live_win_close"), for: .normal)
        button.addTarget(self, action: #selector(closeButtonTapped), for: .touchUpInside)
        button.frame = CGRect(x: 0, y: 0, width: 24, height: 24)
        return button
    }()

    private lazy var closeButtonContainer: UIView = {
        let container = UIView(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
        container.backgroundColor = .clear
        container.addSubview(closeButton)
        closeButton.center = CGPoint(x: container.bounds.width / 2, y: container.bounds.height / 2)
        return container
    }()
    
    private lazy var bottomView: YHGradientView = {
        let view = YHGradientView()
        view.isHidden = true
        view.frame = CGRect(x: 0, y: 0, width: Size.defaultWidth, height: 20)
        return view
    }()
    
    private lazy var bottomImageView: UIImageView = {
        let imageView = UIImageView(image: UIImage(named: "live_player_bg"))
        return imageView
    }()

    // MARK: - Initialization

    override init() {
        containerView = UIView(frame: CGRect(x: 0, y: 0,
                                             width: Size.defaultWidth,
                                             height: Size.defaultHeight))
        contentView = UIView(frame: containerView.bounds)
        super.init()
        setupUI()
        setupGestures()
    }

    // MARK: - Setup

    private func setupUI() {
        containerView.backgroundColor = .black
        containerView.layer.cornerRadius = 3
        containerView.clipsToBounds = true
        containerView.layer.masksToBounds = true

        containerView.layer.shadowColor = UIColor.black.cgColor
        containerView.layer.shadowOffset = CGSize(width: 0, height: 2)
        containerView.layer.shadowRadius = 4
        containerView.layer.shadowOpacity = 0.3
        
        containerView.addSubview(contentView)
        contentView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            contentView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor),
            contentView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor),
            contentView.topAnchor.constraint(equalTo: containerView.topAnchor),
            contentView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor)
        ])
        
        contentView.addSubview(bottomImageView)
        bottomImageView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            bottomImageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
            bottomImageView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
            bottomImageView.topAnchor.constraint(equalTo: contentView.topAnchor),
            bottomImageView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
        ])

        containerView.addSubview(closeButtonContainer)
        closeButtonContainer.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            closeButtonContainer.topAnchor.constraint(equalTo: containerView.topAnchor),
            closeButtonContainer.trailingAnchor.constraint(equalTo: containerView.trailingAnchor),
            closeButtonContainer.widthAnchor.constraint(equalToConstant: 30),
            closeButtonContainer.heightAnchor.constraint(equalToConstant: 30)
        ])
        
        containerView.addSubview(bottomView)
        bottomView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            bottomView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor),
            bottomView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor),
            bottomView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor),
            bottomView.heightAnchor.constraint(equalToConstant: 20)
        ])
    }

    private func setupGestures() {
        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:)))
        // let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(handlePinch(_:)))
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
        tapGesture.delegate = self

        containerView.addGestureRecognizer(panGesture)
        // containerView.addGestureRecognizer(pinchGesture)
        containerView.addGestureRecognizer(tapGesture)
    }

    // MARK: - Public Methods

    func calculateInitialFrame() -> CGRect {
        let width: CGFloat = Size.defaultWidth
        let height: CGFloat = width / videoOrientation.aspectRatio
        let x = UIScreen.main.bounds.width - width - 16
        let y = UIScreen.main.bounds.height - height - 100

        return CGRect(x: x, y: y, width: width, height: height)
    }

    func show(in window: UIWindow) {
        containerView.frame = calculateInitialFrame()
        window.addSubview(containerView)
    }

    func show(in window: UIWindow, at point: CGPoint? = nil) {
        if let point = point {
            containerView.center = point
        } else {
            containerView.frame.origin = CGPoint(
                x: window.bounds.width - containerView.bounds.width - 20,
                y: window.bounds.height - containerView.bounds.height - 100
            )
        }

        window.addSubview(containerView)

        containerView.alpha = 0
        UIView.animate(withDuration: 0.3) {
            self.containerView.alpha = 1
        }
    }

    func dismiss() {
        UIView.animate(withDuration: 0.3, animations: {
            self.containerView.alpha = 0
        }) { _ in
            self.containerView.removeFromSuperview()
        }
    }

    func setVideoSize(_ size: CGSize) {
        let orientation: VideoOrientation = size.width > size.height ? .landscape : .portrait
        if orientation != videoOrientation {
            videoOrientation = orientation
            updateLayoutForOrientation()
        }
    }

    // MARK: - Private Methods

    private func updateLayoutForOrientation() {
//        let currentWidth = containerView.bounds.width
//        let newHeight = currentWidth / videoOrientation.aspectRatio
//
//        UIView.animate(withDuration: 0.3) {
//            var frame = self.containerView.frame
//            frame.size.height = newHeight
//            self.containerView.frame = frame
//            self.delegate?.floatingWindow(self, didChangeSize: frame.size)
//        }
        
        guard let window = UIApplication.shared.yhKeyWindow() else { return }
            
            let currentWidth = containerView.bounds.width
            let newHeight = currentWidth / videoOrientation.aspectRatio
            
            // 计算安全区域
            let safeAreaInsets = window.safeAreaInsets
            let maxHeight = window.bounds.height - safeAreaInsets.top - safeAreaInsets.bottom
            
            // 如果新高度超过最大高度，则反过来调整宽度
            let finalWidth: CGFloat
            let finalHeight: CGFloat
            
            if newHeight > maxHeight {
                finalHeight = maxHeight
                finalWidth = maxHeight * videoOrientation.aspectRatio
            } else {
                finalWidth = currentWidth
                finalHeight = newHeight
            }
            
            // 确保浮窗位置在屏幕范围内
            var newFrame = containerView.frame
            newFrame.size.width = finalWidth
            newFrame.size.height = finalHeight
            
            // 检查右边界
            if newFrame.maxX > window.bounds.width - 16 {
                newFrame.origin.x = window.bounds.width - newFrame.width - 16
            }
            
            // 检查左边界
            if newFrame.minX < 16 {
                newFrame.origin.x = 16
            }
            
            // 检查底部边界
            if newFrame.maxY > window.bounds.height - 44 {
                newFrame.origin.y = window.bounds.height - newFrame.height - 44
            }
            
            // 检查顶部边界
            if newFrame.minY < safeAreaInsets.top + 16 {
                newFrame.origin.y = safeAreaInsets.top + 16
            }
            
            UIView.animate(withDuration: 0.3) {
                self.containerView.frame = newFrame
                self.delegate?.floatingWindow(self, didChangeSize: newFrame.size)
            }
    }

    // MARK: - Gesture Handlers

    @objc private func handlePan(_ gesture: UIPanGestureRecognizer) {
        guard !isResizing else { return }

        let translation = gesture.translation(in: containerView.superview)

        switch gesture.state {
        case .began:
            initialCenter = containerView.center

        case .changed:
            var newCenter = CGPoint(
                x: initialCenter.x + translation.x,
                y: initialCenter.y + translation.y
            )
            newCenter = adjustedPosition(for: newCenter)
            containerView.center = newCenter
            delegate?.floatingWindow(self, didChangePosition: newCenter)

        case .ended:
            let velocity = gesture.velocity(in: containerView.superview)
            handlePanEndedWithVelocity(velocity)

        default:
            break
        }
    }

    private func snapToNearestSize() {
        guard let superview = containerView.superview else { return }

        let currentWidth = containerView.bounds.width
        let screenWidth = superview.bounds.width
        let screenHeight = superview.bounds.height

        // 简化尺寸档位，且确保不超过屏幕宽度的75%
        let maxAllowedWidth = min(Size.maxWidth, screenWidth * 0.75)
        let sizeSteps: [CGFloat] = [
            Size.minWidth,
            Size.defaultWidth,
            maxAllowedWidth * 0.5,
            maxAllowedWidth
        ]

        // 找到最接近的宽度
        let targetWidth = sizeSteps.min(by: { abs($0 - currentWidth) < abs($1 - currentWidth) }) ?? Size.defaultWidth
        let targetHeight = targetWidth / videoOrientation.aspectRatio

        // 确保高度不超过屏幕高度的75%
        let maxAllowedHeight = screenHeight * 0.75
        let finalWidth: CGFloat
        let finalHeight: CGFloat

        if targetHeight > maxAllowedHeight {
            finalHeight = maxAllowedHeight
            finalWidth = finalHeight * videoOrientation.aspectRatio
        } else {
            finalWidth = targetWidth
            finalHeight = targetHeight
        }

        UIView.animate(withDuration: 0.3) {
            var frame = self.containerView.frame

            // 设置新的尺寸
            frame.size = CGSize(width: finalWidth, height: finalHeight)

            // 计算新的中心点，确保不超出屏幕边界
            let centerX = max(finalWidth / 2, min(self.containerView.center.x, screenWidth - finalWidth / 2))
            let centerY = max(finalHeight / 2, min(self.containerView.center.y, screenHeight - finalHeight / 2))

            // 基于新的中心点设置origin
            frame.origin.x = centerX - finalWidth / 2
            frame.origin.y = centerY - finalHeight / 2

            self.containerView.frame = frame
            self.delegate?.floatingWindow(self, didChangeSize: frame.size)
        }
    }

    @objc private func handlePinch(_ gesture: UIPinchGestureRecognizer) {
        guard let superview = containerView.superview else { return }

        switch gesture.state {
        case .began:
            isResizing = true
            initialFrame = containerView.frame

        case .changed:
            let scale = gesture.scale
            let screenWidth = superview.bounds.width
            let screenHeight = superview.bounds.height

            // 计算新的尺寸
            var newWidth = initialFrame.width * scale
            var newHeight = newWidth / videoOrientation.aspectRatio

            // 确保不超过屏幕最大限制（75%的屏幕大小）
            let maxWidth = screenWidth * 0.75
            let maxHeight = screenHeight * 0.75

            if newWidth > maxWidth {
                newWidth = maxWidth
                newHeight = newWidth / videoOrientation.aspectRatio
            }

            if newHeight > maxHeight {
                newHeight = maxHeight
                newWidth = newHeight * videoOrientation.aspectRatio
            }

            // 确保不小于最小尺寸
            if newWidth < Size.minWidth {
                newWidth = Size.minWidth
                newHeight = newWidth / videoOrientation.aspectRatio
            }

            // 保持中心点不变，但确保不超出屏幕边界
            var newCenter = containerView.center

            // 约束中心点，确保视图不会超出屏幕
            newCenter.x = max(newWidth / 2, min(newCenter.x, screenWidth - newWidth / 2))
            newCenter.y = max(newHeight / 2, min(newCenter.y, screenHeight - newHeight / 2))

            // 更新frame
            var newFrame = containerView.frame
            newFrame.size = CGSize(width: newWidth, height: newHeight)
            newFrame.origin.x = newCenter.x - newWidth / 2
            newFrame.origin.y = newCenter.y - newHeight / 2

            containerView.frame = newFrame
            delegate?.floatingWindow(self, didChangeSize: newFrame.size)

        case .ended, .cancelled:
            isResizing = false
            snapToNearestSize()

        default:
            break
        }
    }

    @objc private func handleTap(_ gesture: UITapGestureRecognizer) {
        let location = gesture.location(in: containerView)

        if closeButtonContainer.frame.contains(location) {
            return
        }

        delegate?.floatingWindowDidTap(self)
    }

    @objc private func closeButtonTapped() {
        delegate?.floatingWindowDidClose(self)
        dismiss()
    }

    // MARK: - Helper Methods

    private func constrainSize(_ size: CGSize) -> CGSize {
        var width = size.width
        var height = size.height

        if width < Size.minWidth {
            width = Size.minWidth
        } else if width > Size.maxWidth {
            width = Size.maxWidth
        }

        height = width / videoOrientation.aspectRatio

        if height > Size.maxHeight {
            height = Size.maxHeight
            width = height * videoOrientation.aspectRatio
        }

        return CGSize(width: width, height: height)
    }

//    private func adjustedPosition(for center: CGPoint) -> CGPoint {
//        guard let superview = containerView.superview else { return center }
//
//        var adjustedCenter = center
//        let halfWidth = containerView.bounds.width / 2
//        let halfHeight = containerView.bounds.height / 2
//
//        let safeAreaInsets: UIEdgeInsets
//        if #available(iOS 11.0, *) {
//            safeAreaInsets = superview.safeAreaInsets
//        } else {
//            safeAreaInsets = .zero
//        }
//
//        let topLimit = safeAreaInsets.top + halfHeight
//        let bottomLimit = superview.bounds.height - safeAreaInsets.bottom - halfHeight
//
//        adjustedCenter.x = min(max(halfWidth, adjustedCenter.x),
//                               superview.bounds.width - halfWidth)
//        adjustedCenter.y = min(max(topLimit, adjustedCenter.y),
//                               bottomLimit)
//
//        return adjustedCenter
//    }
//
//    private func handlePanEndedWithVelocity(_ velocity: CGPoint) {
//        let magnitude = sqrt((velocity.x * velocity.x) + (velocity.y * velocity.y))
//        let slideMultiplier = magnitude / 200
//        let slideFactor = 0.1 * slideMultiplier
//
//        var finalCenter = CGPoint(
//            x: containerView.center.x + (velocity.x * slideFactor),
//            y: containerView.center.y + (velocity.y * slideFactor)
//        )
//
//        finalCenter = adjustedPosition(for: finalCenter)
//
//        UIView.animate(withDuration: 0.3) {
//            self.containerView.center = finalCenter
//            self.delegate?.floatingWindow(self, didChangePosition: finalCenter)
//        }
//    }
    
    private func adjustedPosition(for center: CGPoint) -> CGPoint {
        guard let superview = containerView.superview else { return center }

        var adjustedCenter = center
        let halfWidth = containerView.bounds.width / 2
        let halfHeight = containerView.bounds.height / 2

        let safeAreaInsets: UIEdgeInsets
        if #available(iOS 11.0, *) {
            safeAreaInsets = superview.safeAreaInsets
        } else {
            safeAreaInsets = .zero
        }

        // 设置固定的边距
        let topMargin: CGFloat = 86 // 距离顶部statusbar 86
        let bottomMargin: CGFloat = 86 // 距离底部安全区域 86
        let horizontalMargin: CGFloat = 20 // 左右边距 20

        // 计算活动范围的限制
        let topLimit = max(safeAreaInsets.top + topMargin, halfHeight)
        let bottomLimit = superview.bounds.height - max(safeAreaInsets.bottom + bottomMargin, halfHeight)
        let leftLimit = horizontalMargin + halfWidth
        let rightLimit = superview.bounds.width - horizontalMargin - halfWidth

        // 应用限制
        adjustedCenter.x = min(max(leftLimit, adjustedCenter.x), rightLimit)
        adjustedCenter.y = min(max(topLimit, adjustedCenter.y), bottomLimit)

        return adjustedCenter
    }

    private func handlePanEndedWithVelocity(_ velocity: CGPoint) {
        let magnitude = sqrt((velocity.x * velocity.x) + (velocity.y * velocity.y))
        let slideMultiplier = magnitude / 200
        let slideFactor = 0.1 * slideMultiplier

        var finalCenter = CGPoint(
            x: containerView.center.x + (velocity.x * slideFactor),
            y: containerView.center.y + (velocity.y * slideFactor)
        )

        finalCenter = adjustedPosition(for: finalCenter)

        // 确定最终吸附位置（左右两侧）
        guard let superview = containerView.superview else { return }
        let horizontalMargin: CGFloat = 20
        let shouldMoveToRight = finalCenter.x > superview.bounds.width / 2

        // 计算吸附后的 x 坐标
        let finalX = shouldMoveToRight ?
            (superview.bounds.width - horizontalMargin - containerView.bounds.width / 2) :
            (horizontalMargin + containerView.bounds.width / 2)

        // 保持 y 坐标不变，但确保在限制范围内
        let finalY = finalCenter.y

        UIView.animate(withDuration: 0.3) {
            self.containerView.center = CGPoint(x: finalX, y: finalY)
            self.delegate?.floatingWindow(self, didChangePosition: CGPoint(x: finalX, y: finalY))
        }
    }
}

// MARK: - UIGestureRecognizerDelegate

extension YHFloatingWindow: UIGestureRecognizerDelegate {
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer,
                           shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer,
                           shouldReceive touch: UITouch) -> Bool {
        let location = touch.location(in: containerView)
        if closeButtonContainer.frame.contains(location) {
            return false
        }
        return true
    }
}

// MARK: - YHPlayerDelegate

extension YHFloatingWindow: YHPlayerDelegate {
    func player(_ player: YHPlayer, didChangedToState state: AgoraMediaPlayerState, reason: AgoraMediaPlayerReason) {
        //
    }
    func player(_ player: YHPlayer, didChangedToPosition position: Int) {
        //
    }
    func player(_ player: YHPlayer, didReceiveVideoSize size: CGSize) {
//        DispatchQueue.main.async {
//            self.setVideoSize(size)
//        }
    }
    func player(_ player: YHPlayer, didChangedTo positionMs: Int, atTimestamp timestampMs: TimeInterval) {
        //
    }
}
