package com.rosetta.messenger.network

class ReadyPacketGate(
    private val maxSize: Int,
    private val ttlMs: Long
) {
    private data class QueuedPacket(
        val packet: Packet,
        val accountPublicKey: String,
        val queuedAtMs: Long
    )

    private val queue = ArrayDeque<QueuedPacket>()

    fun clear(reason: String, addLog: (String) -> Unit) {
        val clearedCount =
            synchronized(queue) {
                val count = queue.size
                queue.clear()
                count
            }
        if (clearedCount > 0) {
            addLog("🧹 READY-GATE queue cleared: $clearedCount packet(s), reason=$reason")
        }
    }

    fun enqueue(
        packet: Packet,
        accountPublicKey: String,
        state: ConnectionLifecycleState,
        shortKeyForLog: (String) -> String,
        addLog: (String) -> Unit
    ) {
        val now = System.currentTimeMillis()
        val packetId = packet.getPacketId()
        synchronized(queue) {
            while (queue.isNotEmpty()) {
                val oldest = queue.first()
                if (now - oldest.queuedAtMs <= ttlMs) break
                queue.removeFirst()
            }
            while (queue.size >= maxSize) {
                queue.removeFirst()
            }
            queue.addLast(
                QueuedPacket(
                    packet = packet,
                    accountPublicKey = accountPublicKey,
                    queuedAtMs = now
                )
            )
        }
        addLog(
            "📦 READY-GATE queued id=0x${packetId.toString(16)} state=$state account=${shortKeyForLog(accountPublicKey)}"
        )
    }

    fun drainForAccount(
        activeAccountKey: String,
        reason: String,
        addLog: (String) -> Unit
    ): List<Packet> {
        if (activeAccountKey.isBlank()) return emptyList()

        val now = System.currentTimeMillis()
        val packetsToSend = mutableListOf<Packet>()

        synchronized(queue) {
            val iterator = queue.iterator()
            while (iterator.hasNext()) {
                val queued = iterator.next()
                val isExpired = now - queued.queuedAtMs > ttlMs
                val accountMatches =
                    queued.accountPublicKey.isBlank() ||
                        queued.accountPublicKey.equals(activeAccountKey, ignoreCase = true)
                if (!isExpired && accountMatches) {
                    packetsToSend += queued.packet
                }
                iterator.remove()
            }
        }

        if (packetsToSend.isNotEmpty()) {
            addLog("📬 READY-GATE flush: ${packetsToSend.size} packet(s), reason=$reason")
        }
        return packetsToSend
    }
}
