package com.fabledsword.minstrel.api

import com.fabledsword.minstrel.auth.AuthStore
import okhttp3.Interceptor
import okhttp3.Response
import javax.inject.Inject
import javax.inject.Singleton

/**
 * Attaches the session cookie from [AuthStore] to Minstrel-server
 * requests, captures Set-Cookie from successful responses (login
 * flow), and clears the store on 401 so downstream code can react
 * to logout.
 *
 * Mirrors the Flutter Dio interceptor pattern.
 *
 * Scoped to the [BaseUrlInterceptor.PLACEHOLDER_HOST] sentinel host
 * the same way BaseUrlInterceptor is. Drift #568 / #569 caught two
 * leaks here: (1) the session cookie was being attached to every
 * external request the shared OkHttpClient services — including
 * Coil image fetches to artwork.musicbrainz.org / coverartarchive.org
 * / Lidarr's /MediaCover endpoints — exposing the session
 * identifier to third-party logging; (2) a 401 from any of those
 * external hosts silently wiped the user's Minstrel session.
 * Restricting both attach + clear to placeholder-host requests
 * closes both gaps.
 */
@Singleton
class AuthCookieInterceptor @Inject constructor(
    private val authStore: AuthStore,
) : Interceptor {

    override fun intercept(chain: Interceptor.Chain): Response {
        val original = chain.request()
        if (original.url.host != BaseUrlInterceptor.PLACEHOLDER_HOST) {
            // External request — no Minstrel session cookie attached,
            // and a 401 from this host does NOT clear the user's
            // session. Pass through untouched.
            return chain.proceed(original)
        }
        val cookie = authStore.sessionCookie.value
        val request = original.newBuilder().apply {
            if (!cookie.isNullOrEmpty()) header("Cookie", cookie)
        }.build()

        val response = chain.proceed(request)

        if (response.code == HTTP_UNAUTHORIZED) {
            authStore.setSessionCookie(null)
        } else if (response.isSuccessful) {
            // Capture the first Set-Cookie pair on login; subsequent
            // responses that include Set-Cookie keep the store fresh.
            response.headers("Set-Cookie").firstOrNull()?.let { sc ->
                val firstPair = sc.substringBefore(';')
                if (firstPair.isNotBlank()) authStore.setSessionCookie(firstPair)
            }
        }
        return response
    }

    private companion object {
        const val HTTP_UNAUTHORIZED = 401
    }
}
