import Foundation
import WebRTC

protocol WebRTCClientDelegate: AnyObject {
    /// ICE 连接建立（可以开始远程控制）
    func webRTCClientDidConnect()
    /// 连接断开（远端断开或网络故障）
    func webRTCClientDidDisconnect()
    /// 连接失败
    func webRTCClient(didFail error: String)
    /// 被控端上报当前串流模式（0=WebRTC 1=自编码）
    func webRTCClient(didReportStreamMode mode: Int)
    /// 被控端上报当前采集分辨率
    func webRTCClient(didReportResolution width: Int, height: Int)
    /// 被控端上报当前采集帧率与支持的帧率档位（按屏幕刷新率筛选，升序）
    func webRTCClient(didReportFps fps: Int, supportedFps: [Int])
}

/// WebRTC 客户端：负责 PeerConnection 的创建、Offer/Answer 协商、
/// ICE 候选交换、控制/视频 DataChannel 管理与统计信息获取。
/// 与 Android 端 WebRtcClient 行为保持一致。
final class WebRTCClient: NSObject {

    static let streamModeWebRTC: Int32 = 0
    static let streamModeSelfCodec: Int32 = 1

    private static let controlChannelLabel = "control_channel"
    private static let videoChannelLabel = "video_channel"

    private static let factory: RTCPeerConnectionFactory = {
        RTCInitializeSSL()
        return RTCPeerConnectionFactory(
            encoderFactory: RTCDefaultVideoEncoderFactory(),
            decoderFactory: RTCDefaultVideoDecoderFactory())
    }()

    weak var delegate: WebRTCClientDelegate?
    /// 自编码模式的 H.264 裸流解码器（video_channel 二进制数据直接转发给它）
    var selfCodecDecoder: SelfCodecDecoder?

    private let signaling: SignalingClient
    private let myDeviceId: String
    private var targetDeviceId: String = ""
    private var peerConnection: RTCPeerConnection?
    private var controlChannel: RTCDataChannel?
    private var videoChannel: RTCDataChannel?
    private weak var remoteRenderer: RTCVideoRenderer?
    private var remoteVideoTrack: RTCVideoTrack?
    private var connected = false

    init(signaling: SignalingClient, myDeviceId: String) {
        self.signaling = signaling
        self.myDeviceId = myDeviceId
        super.init()
    }

    var isDataChannelOpen: Bool {
        controlChannel?.readyState == .open
    }

    // MARK: - 连接流程

    /// 创建 PeerConnection 与 DataChannel，并向目标设备发送 Offer（携带鉴权信息）。
    func createOffer(targetDeviceId: String,
                     renderer: RTCVideoRenderer,
                     authType: String?,
                     authValue: String?) {
        self.targetDeviceId = targetDeviceId
        self.remoteRenderer = renderer

        let config = RTCConfiguration()
        config.iceServers = [
            RTCIceServer(urlStrings: ["stun:stun.l.google.com:19302"]),
            RTCIceServer(urlStrings: ["stun:www.ttstd.com:3478"]),
            RTCIceServer(urlStrings: ["turn:www.ttstd.com:3478"],
                         username: "ttstd",
                         credential: "ttstd123")
        ]
        config.sdpSemantics = .unifiedPlan
        config.continualGatheringPolicy = .gatherContinually
        config.iceCandidatePoolSize = 10
        config.iceTransportPolicy = .all

        let pcConstraints = RTCMediaConstraints(mandatoryConstraints: nil, optionalConstraints: nil)
        guard let pc = Self.factory.peerConnection(with: config, constraints: pcConstraints, delegate: self) else {
            notifyFail("PeerConnection 创建失败")
            return
        }
        peerConnection = pc

        // 只接收视频，不发送本地媒体
        let transceiverInit = RTCRtpTransceiverInit()
        transceiverInit.direction = .recvOnly
        pc.addTransceiver(of: .video, init: transceiverInit)

        // 控制通道：可靠、有序
        let controlConfig = RTCDataChannelConfiguration()
        controlConfig.isOrdered = true
        controlChannel = pc.dataChannel(forLabel: Self.controlChannelLabel, configuration: controlConfig)
        controlChannel?.delegate = self

        // 自编码视频通道：不可靠、低延迟（丢帧优先）
        let videoConfig = RTCDataChannelConfiguration()
        videoConfig.isOrdered = false
        videoConfig.maxRetransmits = 0
        videoChannel = pc.dataChannel(forLabel: Self.videoChannelLabel, configuration: videoConfig)
        videoChannel?.delegate = self

        let offerConstraints = RTCMediaConstraints(
            mandatoryConstraints: [
                "OfferToReceiveVideo": "true",
                "OfferToReceiveAudio": "false"
            ],
            optionalConstraints: nil)

        pc.offer(for: offerConstraints) { [weak self] sdp, error in
            guard let self else { return }
            if let error {
                self.notifyFail("创建 Offer 失败: \(error.localizedDescription)")
                return
            }
            guard let sdp else {
                self.notifyFail("创建 Offer 失败: SDP 为空")
                return
            }
            pc.setLocalDescription(sdp) { [weak self] error in
                guard let self else { return }
                if let error {
                    self.notifyFail("设置本地 SDP 失败: \(error.localizedDescription)")
                    return
                }
                self.sendOffer(sdp: sdp.sdp, authType: authType, authValue: authValue)
            }
        }
    }

    private func sendOffer(sdp: String, authType: String?, authValue: String?) {
        var msg = SignalMessage()
        msg.type = "OFFER"
        msg.fromDeviceId = myDeviceId
        msg.toDeviceId = targetDeviceId
        msg.payload = SignalMessage.encodePayload(["sdp": sdp])
        msg.authType = authType
        msg.authValue = authValue
        signaling.send(msg)
    }

    /// 处理被控端返回的 Answer
    func handleAnswer(sdp: String) {
        let desc = RTCSessionDescription(type: .answer, sdp: sdp)
        peerConnection?.setRemoteDescription(desc) { [weak self] error in
            if let error {
                self?.notifyFail("设置远端 SDP 失败: \(error.localizedDescription)")
            }
        }
    }

    /// 添加远端 ICE 候选
    func addIceCandidate(sdpMid: String, sdpMLineIndex: Int32, candidate: String) {
        let ice = RTCIceCandidate(sdp: candidate, sdpMLineIndex: sdpMLineIndex, sdpMid: sdpMid)
        peerConnection?.add(ice) { error in
            if let error {
                NSLog("[WebRTC] addIceCandidate error: \(error.localizedDescription)")
            }
        }
    }

    // MARK: - 控制指令

    func sendControlCommand(_ message: ControlMessage) {
        guard let channel = controlChannel, channel.readyState == .open else { return }
        let buffer = RTCDataBuffer(data: message.serializedData(), isBinary: true)
        channel.sendData(buffer)
    }

    /// 请求被控端切换采集分辨率（width=0 表示恢复原生分辨率）
    func requestResolutionChange(width: Int32, height: Int32, fps: Int32) {
        var msg = ControlMessage()
        msg.action = .setResolution
        msg.width = width
        msg.height = height
        msg.fps = fps
        sendControlCommand(msg)
    }

    /// 请求被控端切换串流模式（0=WebRTC 1=自编码）
    func sendStreamMode(_ mode: Int32) {
        var msg = ControlMessage()
        msg.action = .setStreamMode
        msg.streamMode = mode
        sendControlCommand(msg)
    }

    // MARK: - 统计

    func stats(_ completion: @escaping (RTCStatisticsReport) -> Void) {
        peerConnection?.statistics(completionHandler: completion)
    }

    // MARK: - 关闭

    func close() {
        connected = false
        controlChannel?.close()
        videoChannel?.close()
        controlChannel = nil
        videoChannel = nil
        if let track = remoteVideoTrack, let renderer = remoteRenderer {
            track.remove(renderer)
        }
        remoteVideoTrack = nil
        peerConnection?.close()
        peerConnection = nil
    }

    private func notifyFail(_ text: String) {
        DispatchQueue.main.async {
            self.delegate?.webRTCClient(didFail: text)
        }
    }
}

// MARK: - RTCPeerConnectionDelegate

extension WebRTCClient: RTCPeerConnectionDelegate {

    func peerConnection(_ peerConnection: RTCPeerConnection, didChange stateChanged: RTCSignalingState) {}

    func peerConnection(_ peerConnection: RTCPeerConnection, didAdd stream: RTCMediaStream) {}

    func peerConnection(_ peerConnection: RTCPeerConnection, didRemove stream: RTCMediaStream) {}

    func peerConnectionShouldNegotiate(_ peerConnection: RTCPeerConnection) {}

    func peerConnection(_ peerConnection: RTCPeerConnection, didChange newState: RTCIceConnectionState) {
        DispatchQueue.main.async {
            switch newState {
            case .connected, .completed:
                if !self.connected {
                    self.connected = true
                    self.delegate?.webRTCClientDidConnect()
                }
            case .disconnected, .failed, .closed:
                if self.connected {
                    self.connected = false
                    self.delegate?.webRTCClientDidDisconnect()
                } else if newState == .failed {
                    self.delegate?.webRTCClient(didFail: "ICE 连接失败")
                }
            default:
                break
            }
        }
    }

    func peerConnection(_ peerConnection: RTCPeerConnection, didChange newState: RTCIceGatheringState) {}

    func peerConnection(_ peerConnection: RTCPeerConnection, didGenerate candidate: RTCIceCandidate) {
        var msg = SignalMessage()
        msg.type = "ICE_CANDIDATE"
        msg.fromDeviceId = myDeviceId
        msg.toDeviceId = targetDeviceId
        msg.payload = SignalMessage.encodePayload([
            "sdpMid": candidate.sdpMid ?? "",
            "sdpMLineIndex": Int(candidate.sdpMLineIndex),
            "candidate": candidate.sdp
        ])
        signaling.send(msg)
    }

    func peerConnection(_ peerConnection: RTCPeerConnection, didRemove candidates: [RTCIceCandidate]) {}

    func peerConnection(_ peerConnection: RTCPeerConnection, didOpen dataChannel: RTCDataChannel) {
        // 作为 Offer 方，通道由本端创建；此回调用于兜底远端创建的通道
        dataChannel.delegate = self
        if dataChannel.label == Self.videoChannelLabel {
            videoChannel = dataChannel
        } else if dataChannel.label == Self.controlChannelLabel {
            controlChannel = dataChannel
        }
    }

    func peerConnection(_ peerConnection: RTCPeerConnection,
                        didAdd rtpReceiver: RTCRtpReceiver,
                        streams mediaStreams: [RTCMediaStream]) {
        guard let track = rtpReceiver.track as? RTCVideoTrack else { return }
        DispatchQueue.main.async {
            self.remoteVideoTrack = track
            if let renderer = self.remoteRenderer {
                track.add(renderer)
            }
        }
    }
}

// MARK: - RTCDataChannelDelegate

extension WebRTCClient: RTCDataChannelDelegate {

    func dataChannelDidChangeState(_ dataChannel: RTCDataChannel) {
        NSLog("[WebRTC] DataChannel \(dataChannel.label) state: \(dataChannel.readyState.rawValue)")
    }

    func dataChannel(_ dataChannel: RTCDataChannel, didReceiveMessageWith buffer: RTCDataBuffer) {
        if dataChannel.label == Self.videoChannelLabel {
            // 自编码 H.264 裸流分片
            selfCodecDecoder?.onBinaryMessage(buffer.data)
            return
        }
        // 控制通道：被控端上报（串流模式 / 分辨率）
        guard buffer.isBinary, let msg = ControlMessage.parse(from: buffer.data) else { return }
        DispatchQueue.main.async {
            switch msg.action {
            case .reportStreamMode:
                self.delegate?.webRTCClient(didReportStreamMode: Int(msg.streamMode))
            case .reportResolution:
                self.delegate?.webRTCClient(didReportResolution: Int(msg.width), height: Int(msg.height))
                self.delegate?.webRTCClient(didReportFps: Int(msg.fps),
                                            supportedFps: msg.supportedFps.map(Int.init))
            default:
                break
            }
        }
    }
}
