/*
 * Hermes Node Android
 * Copyright (C) 2026 Stefy Lanza <stefy@nexlab.net>
 * SPDX-License-Identifier: GPL-3.0-or-later
 */
package net.nexlab.hermesnodeandroid

import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.WebSocket
import okhttp3.WebSocketListener
import java.security.SecureRandom
import java.security.cert.X509Certificate
import java.util.concurrent.TimeUnit
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager

class GatewayClient(
    private val config: NodeConfig,
) {
    private val client = buildClient(config.insecureTls)
    private var socket: WebSocket? = null

    fun connect(listener: WebSocketListener) {
        val request = Request.Builder()
            .url(urlWithToken(config.gatewayUrl, config.token))
            .addHeader("Authorization", "Bearer ${config.token}")
            .build()
        socket = client.newWebSocket(request, listener)
    }

    private fun urlWithToken(baseUrl: String, token: String): String {
        val separator = if (baseUrl.contains("?")) "&" else "?"
        return baseUrl + separator + "token=" + java.net.URLEncoder.encode(token, Charsets.UTF_8.name())
    }

    fun send(text: String): Boolean = socket?.send(text) == true

    fun close() {
        socket?.close(1000, "Hermes Node Android stopping")
        socket = null
    }

    private fun buildClient(insecureTls: Boolean): OkHttpClient {
        val builder = OkHttpClient.Builder()
            .pingInterval(30, TimeUnit.SECONDS)
            .connectTimeout(20, TimeUnit.SECONDS)
            .readTimeout(0, TimeUnit.SECONDS)
        if (insecureTls) {
            val trustAll = object : X509TrustManager {
                override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) = Unit
                override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) = Unit
                override fun getAcceptedIssuers(): Array<X509Certificate> = emptyArray()
            }
            val sslContext = SSLContext.getInstance("TLS")
            sslContext.init(null, arrayOf<TrustManager>(trustAll), SecureRandom())
            builder.sslSocketFactory(sslContext.socketFactory, trustAll)
            builder.hostnameVerifier { _, _ -> true }
        }
        return builder.build()
    }
}
