//
//  PhoneStateMonitor.swift
//  ylgamehall
//
//  电话状态监听（Phase 8.4，契约 §3.1 ［14］ phonestate 反向 callback）。
//
//  msext 用已废弃的 `CTCallCenter`（iOS 10+ deprecated）；本项目用 CallKit
//  `CXCallObserver`（iOS 10+ 推荐），语义等价，对 H5 输出的字符串一致：
//    - "2" = 来电响铃中（hasConnected=false, isOutgoing=false, hasEnded=false）
//           或 已连接（hasConnected=true，无论 incoming/outgoing）
//    - "0" = 挂断（hasEnded=true）
//    - 其它（拨出中未连接、保持等）不发
//
//  仅子游戏注册，大厅不发（msext gameController.m 同款；契约表注「已注释」表示
//  msext 在线版当前不主动触发，但 H5 子游戏仍按契约处理收到的事件）。
//
//  使用模式（与 BatteryMonitor / NetworkMonitor 一致）：
//    - viewDidLoad / setupExternalSubscriptions：`shared.start()` + `onChange = { ... }`
//    - viewWillDisappear / teardownExternalSubscriptions：`onChange = nil` + `shared.stop()`
//

import Foundation
import CallKit

@MainActor
public final class PhoneStateMonitor: NSObject {

    public static let shared = PhoneStateMonitor()

    /// 状态变化回调，参数即给 H5 的 `phonestate` 字符串（"2" / "0"）。
    /// closure 在 main actor 上调，调用方可直接拿 bridge 反向 callback。
    public var onChange: ((String) -> Void)?

    private var observer: CXCallObserver?

    public override init() {
        super.init()
    }

    /// 开始监听。重复调安全（已 start 则无操作）。
    public func start() {
        guard observer == nil else { return }
        let o = CXCallObserver()
        // queue: nil → main queue（callObserver:callChanged: 回调线程一致，
        // 子游戏页 bridge.call 也走主线程，无并发问题）
        o.setDelegate(self, queue: nil)
        observer = o
    }

    /// 停止监听。stop 之后再 start 重新创建 observer。
    public func stop() {
        observer?.setDelegate(nil, queue: nil)
        observer = nil
    }
}

extension PhoneStateMonitor: CXCallObserverDelegate {

    /// CXCallObserver 状态切换。本方法 `@objc` 由 CallKit 在主队列调（init 时传 nil）。
    public nonisolated func callObserver(_ callObserver: CXCallObserver, callChanged call: CXCall) {
        let state: String
        if call.hasEnded {
            state = "0"
        } else if call.hasConnected {
            // 已接通（任何方向）— 视频房 / 录音应静音
            state = "2"
        } else if !call.isOutgoing {
            // 来电响铃中（hasEnded=false, hasConnected=false, isOutgoing=false）
            state = "2"
        } else {
            // 拨出中未连接 / 保持等中间态 — H5 不关心，丢弃
            return
        }
        Task { @MainActor in
            Self.shared.onChange?(state)
        }
    }
}
