package dev.ulfrx.recipe.auth

import io.ktor.server.config.ApplicationConfig

/**
 * Server OIDC configuration (D-12, D-21..D-22).
 *
 * Values come from `application.conf` (`oidc { ... }`) overridden by
 * `OIDC_ISSUER` / `OIDC_AUDIENCE` / `OIDC_JWKS_URL` env vars at deploy time. The
 * pinned defaults match `Constants.OIDC_ISSUER` / `Constants.OIDC_CLIENT_ID` so
 * dev runs against the documented Authentik provider playbook
 * (`docs/authentik-setup.md`) without extra wiring.
 *
 * `jwksUrl` is required: D-22 mandates a `JwkProvider` with explicit cache + rate
 * limits. If the deployer omits it, `fromApplicationConfig` derives the standard
 * Authentik path (`{issuer}jwks/`). The trailing-slash invariant on `issuer` is
 * enforced by [Constants.OIDC_ISSUER] / `application.conf`.
 */
public data class AuthConfig(
    val issuer: String,
    val audience: String,
    val jwksUrl: String,
    val leewaySeconds: Long = 30L,
) {
    public companion object {
        public fun fromApplicationConfig(config: ApplicationConfig): AuthConfig {
            val issuer = config.property("oidc.issuer").getString()
            val audience = config.property("oidc.audience").getString()
            val jwksUrl =
                config.propertyOrNull("oidc.jwksUrl")?.getString()?.takeIf { it.isNotBlank() }
                    ?: "${issuer.trimEnd('/')}/jwks/"
            val leewaySeconds =
                config.propertyOrNull("oidc.leewaySeconds")?.getString()?.toLongOrNull() ?: 30L
            return AuthConfig(
                issuer = issuer,
                audience = audience,
                jwksUrl = jwksUrl,
                leewaySeconds = leewaySeconds,
            )
        }
    }
}
