package com.anypreta.bountyboard.data.net

import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.Interceptor
import okhttp3.Response
import java.util.concurrent.atomic.AtomicReference

/**
 * Holds the user-configurable base URL and rewrites every outgoing request's
 * scheme/host/port to point at it. Lets the base URL change at runtime (from the
 * login screen) without rebuilding Retrofit.
 */
class HostSelectionInterceptor(initial: String) : Interceptor {

    private val base = AtomicReference(normalize(initial))

    fun setBaseUrl(url: String) {
        base.set(normalize(url))
    }

    fun currentHost(): String? = base.get().toHttpUrlOrNull()?.host

    override fun intercept(chain: Interceptor.Chain): Response {
        val target = base.get().toHttpUrlOrNull() ?: return chain.proceed(chain.request())
        val original = chain.request()
        val newUrl = original.url.newBuilder()
            .scheme(target.scheme)
            .host(target.host)
            .port(target.port)
            .build()
        val req = original.newBuilder().url(newUrl).build()
        return chain.proceed(req)
    }

    companion object {
        fun normalize(url: String): String {
            var u = url.trim()
            if (u.isEmpty()) return "https://bountyboard.anypreta.com/"
            if (!u.startsWith("http://") && !u.startsWith("https://")) u = "https://$u"
            if (!u.endsWith("/")) u += "/"
            return u
        }
    }
}

/**
 * Double-submit CSRF: copy the `bb_csrf` cookie into the `X-CSRF-Token` header on
 * every mutating request (everything but GET/HEAD/OPTIONS).
 */
class CsrfInterceptor(private val cookieJar: PersistentCookieJar) : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val req = chain.request()
        val method = req.method.uppercase()
        if (method == "GET" || method == "HEAD" || method == "OPTIONS") {
            return chain.proceed(req)
        }
        val csrf = cookieJar.cookieValue(req.url.host, "bb_csrf")
        val out = if (csrf != null && req.header("X-CSRF-Token") == null) {
            req.newBuilder().header("X-CSRF-Token", csrf).build()
        } else req
        return chain.proceed(out)
    }
}
