package com.system.cloudservice.engine

import com.system.cloudservice.util.Logger
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.json.JSONObject
import java.net.DatagramPacket
import java.net.DatagramSocket
import java.net.InetSocketAddress

/**
 * BIND-05：UDP 8898 beacon 自动发现，与设备端 Python `sdk/agent/sdk_discovery.py`
 * 及服务端 `sdk/app/services/discovery_service.py` 协议对齐。
 *
 * SDK 每 5s 向局域网广播 {magic:"WORKPHONE_SDK", port, ws_path, ips:[...]}；
 * 本类监听该端口，挑选最优私网 IP（优先 192.168.110.x），返回 WS 基址。
 *
 * 与 LanDiscovery（TCP 子网扫描）互补：beacon 优先、延迟更低、命中即返回。
 */
object BeaconDiscovery {

    private const val BEACON_PORT = 8898
    private const val BEACON_MAGIC = "WORKPHONE_SDK"

    /**
     * 监听 beacon，命中即返回；超时返回 null。
     * @param timeoutMs 监听总时长（默认 20s，对齐 WP_DISCOVER_TIMEOUT）
     */
    suspend fun discover(timeoutMs: Long = 20_000L): DiscoveredServer? = withContext(Dispatchers.IO) {
        val deadline = System.currentTimeMillis() + timeoutMs
        var sock: DatagramSocket? = null
        try {
            sock = DatagramSocket(null).apply {
                reuseAddress = true
                soTimeout = 1_000
                // 绑 8898 接收广播；失败则绑任意端口（部分系统受限）
                try {
                    bind(InetSocketAddress(BEACON_PORT))
                } catch (_: Exception) {
                    bind(InetSocketAddress(0))
                }
            }
            val buf = ByteArray(4096)
            while (System.currentTimeMillis() < deadline) {
                try {
                    val pkt = DatagramPacket(buf, buf.size)
                    sock.receive(pkt)
                    val text = String(pkt.data, 0, pkt.length, Charsets.UTF_8)
                    val parsed = parseBeacon(text)
                    if (parsed != null) {
                        Logger.i("BeaconDiscovery: 发现 SDK ${parsed.wsUrl}")
                        return@withContext parsed
                    }
                } catch (_: java.net.SocketTimeoutException) {
                    // 继续等到 deadline
                } catch (e: Exception) {
                    Logger.d("BeaconDiscovery recv 异常: ${e.message}")
                }
            }
        } catch (e: Exception) {
            Logger.w("BeaconDiscovery 启动失败: ${e.message}")
        } finally {
            try { sock?.close() } catch (_: Exception) {}
        }
        null
    }

    private fun parseBeacon(text: String): DiscoveredServer? {
        return try {
            val obj = JSONObject(text)
            if (obj.optString("magic") != BEACON_MAGIC) return null
            val port = obj.optInt("port", 8899)
            val wsPath = obj.optString("ws_path", "/ws/device").trimEnd('/')
            val ipsArr = obj.optJSONArray("ips")
            val ips = mutableListOf<String>()
            if (ipsArr != null) {
                for (i in 0 until ipsArr.length()) ips.add(ipsArr.optString(i))
            }
            val host = pickBestIp(ips) ?: return null
            DiscoveredServer(host, port, "ws://$host:$port$wsPath", "beacon ($host:$port)")
        } catch (_: Exception) {
            null
        }
    }

    /** 优先 192.168.110.x（工作机常用网段），否则取第一个私网 IP。 */
    private fun pickBestIp(ips: List<String>): String? {
        if (ips.isEmpty()) return null
        ips.firstOrNull { it.startsWith("192.168.110.") }?.let { return it }
        ips.firstOrNull { it.startsWith("192.168.") || it.startsWith("10.") || it.startsWith("172.") }?.let { return it }
        return ips.first()
    }
}
