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

import AgoraRtcKit
import Foundation

// MARK: - 播放器类型
enum YHPlayerType {
    case main
    case secondary
}

// MARK: - 播放模式
enum YHPlayMode {
    case live    // 直播
    case vod     // 点播
}

protocol YHPlayerDelegate: AnyObject {
    func player(_ player: YHPlayer, didChangedToState state: AgoraMediaPlayerState, reason: AgoraMediaPlayerReason)
    func player(_ player: YHPlayer, didChangedToPosition position: Int)
    func player(_ player: YHPlayer, didReceiveVideoSize size: CGSize)
    func player(_ player: YHPlayer, didChangedTo positionMs: Int, atTimestamp timestampMs: TimeInterval)
    func player(_ player: YHPlayer, remoteVideoStats stats: AgoraRtcRemoteVideoStats)
}

extension YHPlayerDelegate {
    func player(_ player: YHPlayer, remoteVideoStats stats: AgoraRtcRemoteVideoStats) {}
}

// MARK: - 播放器实例封装
class YHPlayer {
    // MARK: - Properties
    weak var delegate: YHPlayerDelegate?
    let type: YHPlayerType
    var playerKit: AgoraRtcMediaPlayerProtocol?
    weak var agoraKit: AgoraRtcEngineKit?
    
    private(set) var currentURL: String?
    weak var currentPlayView: UIView?
    private(set) var currentTitle: String?
    private(set) var currentChannelId: String?
    private(set) var currentToken: String?
    private(set) var currentUid: UInt?
    private(set) var isJoined: Bool = false
    private(set) var playMode: YHPlayMode = .vod
    
    // 保存最后的播放信息用于恢复
    // private var lastPlaybackInfo: (url: String?, title: String?, mode: YHPlayMode)?
    
    var isMuted: Bool {
        get { playerKit?.getMute() ?? false }
        set { playerKit?.mute(newValue) }
    }
    
    // MARK: - Initialization
    init(type: YHPlayerType, playerKit: AgoraRtcMediaPlayerProtocol?, agoraKit: AgoraRtcEngineKit?) {
        self.type = type
        self.playerKit = playerKit
        self.agoraKit = agoraKit
        // 基础设置
        playerKit?.setLoopCount(-1)
    }
    
    // MARK: - View Management
    func setPlayModeAndPlayView(_ mode: YHPlayMode, _ view: UIView?) {
        playMode = mode
        currentPlayView = view
        playerKit?.setRenderMode(.fit)
        
        if playMode == .vod {
            // 点播模式：直接设置 MediaPlayer 的视图
            playerKit?.setView(view)
        } else {
            // 直播模式：设置远程视图
            if let view = view, let uid = currentUid {
                setupRemoteVideo(view: view, uid: uid)
            }
        }
    }
    
    func clearPlayerView() {
        currentPlayView = nil
        if playMode == .vod {
            playerKit?.setView(nil)
        } else {
            // 直播模式：设置远程视图
            if let uid = currentUid {
                setupRemoteVideo(view: nil, uid: uid)
            }
        }
    }
    
    private func setupRemoteVideo(view: UIView?, uid: UInt) {
        if type == .secondary {
            // 副播放器使用 Ex 方法
            guard let channelId = currentChannelId else { return }
            let videoCanvas = AgoraRtcVideoCanvas()
            videoCanvas.view = view
            videoCanvas.renderMode = .fit
            videoCanvas.uid = uid
            
            let connection = AgoraRtcConnection()
            connection.channelId = channelId
            connection.localUid = uid
            agoraKit?.setupRemoteVideoEx(videoCanvas, connection: connection)
        } else {
            // 主播放器使用普通方法
            let videoCanvas = AgoraRtcVideoCanvas()
            videoCanvas.view = view
            videoCanvas.renderMode = .fit
            videoCanvas.uid = uid
            agoraKit?.setupRemoteVideo(videoCanvas)
        }
    }
    
    // MARK: - Channel Management
    func setJoinInfo(token: String, channelId: String, uid: UInt) {
        currentToken = token
        currentChannelId = channelId
        currentUid = uid
        isJoined = true
    }
    
    func clearJoinInfo() {
        if let uid = currentUid {
            // 清除远程视图
            let videoCanvas = AgoraRtcVideoCanvas()
            videoCanvas.uid = uid
            videoCanvas.view = nil
            videoCanvas.renderMode = .hidden
            
            if type == .secondary {
                guard let channelId = currentChannelId else { return }
                let connection = AgoraRtcConnection()
                connection.channelId = channelId
                connection.localUid = uid
                agoraKit?.setupRemoteVideoEx(videoCanvas, connection: connection)
            } else {
                agoraKit?.setupRemoteVideo(videoCanvas)
            }
        }
        
        currentToken = nil
        currentChannelId = nil
        currentUid = nil
        isJoined = false
        currentPlayView = nil
        currentURL = nil
        currentTitle = nil
    }
    
    // MARK: - Playback Control
    func play(url: String, title: String? = nil, view: UIView?, isLive: Bool = false) {
        currentURL = url
        currentTitle = title
        setPlayModeAndPlayView(isLive ? .live : .vod, view)
        if !isLive {
            currentPlayView = view
            playerKit?.setRenderMode(.fit)
            playerKit?.setView(view)
            
            let mediaSource = AgoraMediaSource()
            mediaSource.url = url
            mediaSource.autoPlay = true
            let result = playerKit?.open(with: mediaSource)
            if result == 0 {
                playerKit?.play()
            }
        }
    }
    
    func stop() {
        if playMode == .vod {
            playerKit?.stop()
        } else {
            clearJoinInfo()
        }
    }
    
    func pause() {
        if playMode == .vod {
            playerKit?.pause()
        } else {
            YHPlayerManager.shared.leaveChannel(for: self)
        }
    }
    
    func resume() {
        if playMode == .vod {
            if playerKit?.getPlayerState() == .paused {
                playerKit?.resume()
            } else {
                playerKit?.play()
            }
        }
    }
    
    func resume(withNewView view: UIView) {
        if playMode == .vod {
            if let url = currentURL {
                play(url: url,
                     title: currentTitle,
                     view: view,
                     isLive: playMode == .live)
            }
        } else {
            if let token = currentToken,
               let channelId = currentChannelId,
               let uid = currentUid {
                YHPlayerManager.shared.joinChannel(for: self,
                                                 token: token,
                                                 channelId: channelId,
                                                   uid: uid, view: view)
            }
        }
    }
    
    // MARK: - Resource Management
    func reset() {
        stop()
        setPlayModeAndPlayView(playMode, nil)
        delegate = nil
    }
    
    func releasePlayer() {
        reset()
        playerKit = nil
    }
    
    // MARK: - Playback Info & Control
    func getPosition() -> Int {
        return playMode == .vod ? (playerKit?.getPosition() ?? 0) : 0
    }
    
    func getDuration() -> Int {
        return playMode == .vod ? (playerKit?.getDuration() ?? 0) : 0
    }
    
    func getPlayState() -> AgoraMediaPlayerState {
        return playMode == .vod ? (playerKit?.getPlayerState() ?? .idle) : .playing
    }
    
    func seek(to position: Int) {
        if playMode == .vod {
            playerKit?.seek(toPosition: position)
        }
    }
    
    func setVolume(_ volume: Int32) {
        if playMode == .vod {
            playerKit?.adjustPlayoutVolume(volume)
        }
    }
    
    func setPlaybackSpeed(_ speed: Double) {
        if playMode == .vod {
            playerKit?.setPlaybackSpeed(Int32(speed * 100))
        }
    }
}

// MARK: - Factory Methods
extension YHPlayer {
    static func createMainPlayer(playerKit: AgoraRtcMediaPlayerProtocol?,
                               agoraKit: AgoraRtcEngineKit?) -> YHPlayer {
        return YHPlayer(type: .main, playerKit: playerKit, agoraKit: agoraKit)
    }
    
    static func createSecondaryPlayer(playerKit: AgoraRtcMediaPlayerProtocol?,
                                    agoraKit: AgoraRtcEngineKit?) -> YHPlayer {
        return YHPlayer(type: .secondary, playerKit: playerKit, agoraKit: agoraKit)
    }
}
