package ru.forbion.f7cloud.core.push

import android.content.Context
import android.util.Log
import org.json.JSONObject
import ru.forbion.f7cloud.core.auth.AuthSession
import java.io.BufferedReader
import java.io.InputStream
import java.io.InputStreamReader
import java.io.OutputStream
import java.net.HttpURLConnection
import java.net.URL
import java.nio.charset.StandardCharsets
import java.util.UUID

object F7PushRegistrar {
    private const val TAG = "F7PushRegistrar"
    private const val PREFS = "f7push"
    private const val KEY_DEVICE_ID = "device_id"

    fun getDeviceId(context: Context): String {
        val prefs = context.getSharedPreferences(PREFS, Context.MODE_PRIVATE)
        val existing = prefs.getString(KEY_DEVICE_ID, null)
        if (!existing.isNullOrBlank()) {
            return existing
        }
        val id = UUID.randomUUID().toString()
        prefs.edit().putString(KEY_DEVICE_ID, id).apply()
        return id
    }

    fun registerBlocking(
        context: Context,
        session: AuthSession,
        fcmToken: String,
    ): Int {
        val endpoint = session.serverUrl.trimEnd('/') + "/ocs/v2.php/apps/f7push/api/v1/devices"
        val body = JSONObject()
            .put("deviceId", getDeviceId(context))
            .put("fcmToken", fcmToken)
            .put("platform", "android")
            .put("clientApp", "f7cloud-mobile")
            .toString()
        return try {
            postJson(endpoint, session, body)
        } catch (t: Throwable) {
            Log.w(TAG, "register failed", t)
            0
        }
    }

    private fun postJson(endpoint: String, session: AuthSession, json: String): Int {
        val conn = URL(endpoint).openConnection() as HttpURLConnection
        conn.connectTimeout = 15000
        conn.readTimeout = 15000
        conn.requestMethod = "POST"
        conn.doOutput = true
        conn.setRequestProperty("Content-Type", "application/json; charset=utf-8")
        conn.setRequestProperty("Accept", "application/json")
        conn.setRequestProperty("OCS-APIRequest", "true")
        val basic = android.util.Base64.encodeToString(
            "${session.username}:${session.appPassword}".toByteArray(StandardCharsets.UTF_8),
            android.util.Base64.NO_WRAP
        )
        conn.setRequestProperty("Authorization", "Basic $basic")

        val payload = json.toByteArray(StandardCharsets.UTF_8)
        conn.setFixedLengthStreamingMode(payload.size)
        val out: OutputStream = conn.outputStream
        out.write(payload)
        out.close()

        val code = conn.responseCode
        drainQuietly(if (code >= 400) conn.errorStream else conn.inputStream)
        conn.disconnect()
        return code
    }

    private fun drainQuietly(stream: InputStream?) {
        if (stream == null) return
        try {
            BufferedReader(InputStreamReader(stream, StandardCharsets.UTF_8)).use { reader ->
                while (reader.readLine() != null) {
                    // no-op
                }
            }
        } catch (_: Exception) {
        }
    }
}
