package com.jihe.punchnet.sdlan.network

import android.util.Log
import com.jihe.punchnet.PunchnetServiceArgument
import com.jihe.punchnet.api.ConnectResponseData
import com.jihe.punchnet.sdlan.config.Arguments
import com.jihe.punchnet.sdlan.logs.TerminalLogger
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import tech.kwik.core.QuicClientConnection
import java.net.InetSocketAddress
import java.nio.ByteBuffer

suspend fun run_quic_data_plane(
    scope: CoroutineScope, 
    service: com.jihe.punchnet.PunchnetService, 
    argument: Arguments, 
    connectData: ConnectResponseData
) {
    TerminalLogger.infof { "Starting QUIC Data Plane..." }
    
    // Parse the server address from argument.sn (e.g. root.punchsky.com:1265)
    val snParts = argument.sn.split(":")
    val host = snParts[0]
    val port = snParts[1].toIntOrNull() ?: 1265

    while (scope.isActive) {
        var connection: QuicClientConnection? = null
        try {
            TerminalLogger.debugf { "Connecting to QUIC server at $host:$port..." }
            
            // In Kwik, QuicClientConnection is used to connect to a server.
            // Note: Kwik API details may require a specific Builder or config. 
            // We use standard connection parameters.
            val serverAddress = InetSocketAddress(host, port)
            
            val builder = QuicClientConnection.newBuilder()
                .uri(java.net.URI("https://$host:$port"))
                // TODO: configure certificates if self-signed, else default is fine.
            
            connection = builder.build()
            connection.connect()
            
            TerminalLogger.infof { "QUIC connection established!" }

            // Start reading from the TUN interface and sending as QUIC Datagrams
            val jobWrite = scope.launch(Dispatchers.IO) {
                while (isActive) {
                    val data = service.recv()
                    if (data.isEmpty()) {
                        delay(1000)
                        continue
                    }
                    
                    // Send over QUIC Datagram
                    // Note: Kwik Datagram API might be on the connection object.
                    try {
                        // Using datagram sending API from Kwik
                        // If kwik doesn't support datagram directly, we fallback to streams
                        // For RFC 9221 datagrams:
                        // connection.sendDatagram(data) 
                        // Note: Datagram API in Kwik is still experimental in some versions.
                        // We will use stream for fallback if datagram fails compile.
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }
            }
            
            // Start reading QUIC Datagrams from server and write to TUN
            val jobRead = scope.launch(Dispatchers.IO) {
                while (isActive) {
                    // Receive Datagram
                    // val buf = connection.receiveDatagram()
                    // service.send(buf)
                    delay(100)
                }
            }
            
            jobWrite.join()
            jobRead.join()
            
        } catch (e: Exception) {
            TerminalLogger.errorf { "QUIC connection error: ${e.message}" }
            e.printStackTrace()
            delay(3000)
        } finally {
            try {
                connection?.close()
            } catch (e: Exception) {}
        }
    }
}

fun ipToInt(ipAddress: String): Int {
    val parts = ipAddress.split(".")
    if (parts.size != 4) return 0
    var result = 0
    for (i in 0..3) {
        result = result shl 8 or (parts[i].toInt() and 0xFF)
    }
    return result
}
