/*
 * SPDX-License-Identifier: GPL-3.0-or-later
 */
package com.runicgateway.app.core.net

import okhttp3.HttpUrl
import okhttp3.Interceptor
import okhttp3.Response
import java.io.IOException
import javax.inject.Inject
import javax.inject.Singleton

/**
 * Retargets each relative API request onto the runtime-selected base URL
 * (PLAN.md §3). Retrofit is built with a sentinel base host
 * ([BaseUrlHolder.PLACEHOLDER_HOST]); this interceptor swaps the scheme/host/port
 * for the configured shard site and prefixes any base path the user included
 * (`https://host/base`). Absolute-URL requests (the connect probe via `@Url`)
 * carry a real host and pass through untouched.
 */
@Singleton
class HostSelectionInterceptor @Inject constructor(
    private val baseUrlHolder: BaseUrlHolder,
) : Interceptor {

    override fun intercept(chain: Interceptor.Chain): Response {
        val request = chain.request()
        if (request.url.host != BaseUrlHolder.PLACEHOLDER_HOST) {
            return chain.proceed(request)
        }

        val base = baseUrlHolder.current
            ?: throw IOException("No shard website is configured yet.")

        val rewritten = rewriteOntoBase(base, request.url)
        return chain.proceed(request.newBuilder().url(rewritten).build())
    }
}

/**
 * Resolve the sentinel-hosted [requestUrl] against [base] the way a browser
 * resolves a relative link. [base] is guaranteed to end in "/"
 * (ServerUrl.normalize), so `https://host/base/` + `api/v1/x` yields
 * `https://host/base/api/v1/x` — the base path prefix is preserved and no double
 * slash appears. Extracted as a pure function for unit testing.
 */
fun rewriteOntoBase(base: HttpUrl, requestUrl: HttpUrl): HttpUrl {
    val relative = buildString {
        append(requestUrl.encodedPath.removePrefix("/"))
        requestUrl.encodedQuery?.let { append('?').append(it) }
    }
    return base.resolve(relative) ?: base
}
