package dev.ulfrx.recipe.auth

import dev.ulfrx.recipe.shared.Constants
import io.ktor.client.HttpClient
import io.ktor.client.plugins.auth.Auth
import io.ktor.client.plugins.auth.providers.bearer
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.client.plugins.logging.LogLevel
import io.ktor.client.plugins.logging.Logger
import io.ktor.client.plugins.logging.Logging
import io.ktor.http.HttpHeaders
import io.ktor.http.Url
import io.ktor.serialization.kotlinx.json.json
import kotlinx.serialization.json.Json

object AuthHttpClient {
    fun create(authSession: AuthSession): HttpClient =
        HttpClient {
            install(ContentNegotiation) {
                json(authJson)
            }
            install(Auth) {
                bearer {
                    loadTokens {
                        authSession.currentBearerTokens()
                    }
                    refreshTokens {
                        authSession.refreshBearerTokens()
                    }
                    sendWithoutRequest { request ->
                        request.url.host == Url(Constants.API_BASE_URL).host
                    }
                }
            }
            install(Logging) {
                level = LogLevel.HEADERS
                sanitizeHeader { header -> header.equals(HttpHeaders.Authorization, ignoreCase = true) }
                logger =
                    object : Logger {
                        override fun log(message: String) {
                            co.touchlab.kermit.Logger
                                .withTag("auth-http")
                                .i(redact(message))
                        }
                    }
            }
        }

    private fun redact(message: String): String =
        message
            .replace(Regex("Bearer\\s+[^\\s,;]+"), "Bearer <redacted>")
            .replace(Regex("(?i)(Authorization:\\s*)[^\\n\\r]+")) { match ->
                match.groupValues[1] + "<redacted>"
            }

    private val authJson =
        Json {
            ignoreUnknownKeys = true
        }
}
