package ru.forbion.f7cloud.core.auth

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.Request
import ru.forbion.f7cloud.core.network.NetworkFactory
import ru.forbion.f7cloud.core.network.applyOcsJson
import ru.forbion.f7cloud.core.network.isOcsSuccess
import ru.forbion.f7cloud.core.network.ocsData
import ru.forbion.f7cloud.core.network.ocsMeta
import ru.forbion.f7cloud.core.network.parseJsonObject

object AuthVerifier {
    suspend fun verify(session: AuthSession): Result<AuthSession> {
        return runCatching {
            withContext(Dispatchers.IO) {
                val client = NetworkFactory.newAuthedClient(
                    session.username,
                    session.appPassword,
                    session.trustAllCerts,
                    // login-верификация: 401 = «неверный пароль» со своим сообщением, НЕ session-expired
                    throwOnUnauthorized = false,
                )
                val request = Request.Builder()
                    .url("${session.serverUrl.trimEnd('/')}/ocs/v2.php/cloud/user?format=json")
                    .applyOcsJson()
                    .build()
                client.newCall(request).execute().use { response ->
                    if (!response.isSuccessful || response.body == null) {
                        error("Auth failed: HTTP ${response.code}")
                    }
                    val root = parseJsonObject(response.body!!.string(), "профиль пользователя")
                    val meta = root.ocsMeta()
                    if (!isOcsSuccess(meta)) {
                        val message = meta?.optString("message").orEmpty()
                        error("Auth failed: ${message.ifBlank { "HTTP ${response.code}" }}")
                    }
                    val userId = root.ocsData()?.optString("id").orEmpty().trim()
                    session.copy(
                        davUserId = userId.ifBlank { session.username },
                    )
                }
            }
        }.fold(
            onSuccess = { Result.success(it) },
            onFailure = { Result.failure(Exception(it.toLoginErrorMessage(), it)) },
        )
    }
}
