package no.svorka.mcms.ui

import android.content.Context
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import no.svorka.mcms.core.ApiConfiguration
import no.svorka.mcms.core.ApiError
import no.svorka.mcms.core.KeychainStore
import no.svorka.mcms.core.MCMSJson
import no.svorka.mcms.core.McmsConnection

/**
 * Top-level app state: owns the active [McmsConnection], persists the (non-secret)
 * [ApiConfiguration] to SharedPreferences, and keeps credentials in the Keystore.
 */
class AppState(context: Context) {
    private val prefs = context.getSharedPreferences("mcms.app", Context.MODE_PRIVATE)
    private val keychain = KeychainStore(context)

    var configuration by mutableStateOf<ApiConfiguration?>(null)
        private set
    var connection by mutableStateOf<McmsConnection?>(null)
        private set
    var isAuthenticated by mutableStateOf(false)

    val isConfigured: Boolean get() = configuration != null

    init { loadConfiguration() }

    fun configure(config: ApiConfiguration) {
        configuration = config
        connection = makeConnection(config)
        isAuthenticated = false
        prefs.edit().putString("config", MCMSJson.encodeToString(ApiConfiguration.serializer(), config)).apply()
    }

    private fun makeConnection(config: ApiConfiguration): McmsConnection {
        val conn = McmsConnection(config)
        conn.onAuthExpired = { isAuthenticated = false }
        return conn
    }

    private fun loadConfiguration() {
        val json = prefs.getString("config", null) ?: return
        runCatching { MCMSJson.decodeFromString(ApiConfiguration.serializer(), json) }.getOrNull()?.let {
            configuration = it
            connection = makeConnection(it)
        }
    }

    val savedEmail: String? get() = keychain.get("email")

    suspend fun signIn(email: String, password: String, remember: Boolean) {
        val conn = connection ?: throw ApiError.Transport("No connection configured")
        conn.auth.login(email, password)
        // Remember-me persists the email only; the password is never stored at rest.
        if (remember) keychain.set("email", email) else keychain.delete("email")
        keychain.delete("password")   // clear any password persisted by an older build
        isAuthenticated = true
    }

    suspend fun signOut() {
        runCatching { connection?.auth?.logout() }
        keychain.delete("password")   // defence-in-depth: never leave a password behind
        isAuthenticated = false
    }

    /** Reachability probe: a 401/403/404 means the host answered, which is success. */
    suspend fun probe(config: ApiConfiguration): String {
        val conn = McmsConnection(config)
        return try {
            val version = conn.auth.version()
            version.displayVersion?.let { "PON Manager $it" } ?: "Reachable"
        } catch (e: ApiError) {
            when (e) {
                is ApiError.Unauthorized, is ApiError.Forbidden, ApiError.NotFound -> "Reachable — sign in to continue"
                else -> throw e
            }
        }
    }
}
