package com.swoosh.microblog.data.api

import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Assert.*
import org.junit.Before
import org.junit.Test

class GhostAuthInterceptorTest {

    private lateinit var server: MockWebServer

    @Before
    fun setup() {
        server = MockWebServer()
        server.start()
    }

    @After
    fun teardown() {
        server.shutdown()
    }

    @Test
    fun `interceptor adds Authorization header when API key is provided`() {
        val apiKey = "abcdef1234567890:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"
        val interceptor = GhostAuthInterceptor { apiKey }

        val client = OkHttpClient.Builder()
            .addInterceptor(interceptor)
            .build()

        server.enqueue(MockResponse().setResponseCode(200))

        client.newCall(Request.Builder().url(server.url("/test")).build()).execute()

        val recordedRequest = server.takeRequest()
        val authHeader = recordedRequest.getHeader("Authorization")
        assertNotNull("Authorization header should be present", authHeader)
        assertTrue("Should start with 'Ghost '", authHeader!!.startsWith("Ghost "))
        // The rest should be a valid JWT (3 dot-separated parts)
        val token = authHeader.removePrefix("Ghost ")
        assertEquals("JWT should have 3 parts", 3, token.split(".").size)
    }

    @Test
    fun `interceptor does not add Authorization header when API key is null`() {
        val interceptor = GhostAuthInterceptor { null }

        val client = OkHttpClient.Builder()
            .addInterceptor(interceptor)
            .build()

        server.enqueue(MockResponse().setResponseCode(200))

        client.newCall(Request.Builder().url(server.url("/test")).build()).execute()

        val recordedRequest = server.takeRequest()
        val authHeader = recordedRequest.getHeader("Authorization")
        assertNull("Authorization header should not be present", authHeader)
    }

    @Test
    fun `interceptor preserves original request headers`() {
        val apiKey = "abcdef1234567890:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"
        val interceptor = GhostAuthInterceptor { apiKey }

        val client = OkHttpClient.Builder()
            .addInterceptor(interceptor)
            .build()

        server.enqueue(MockResponse().setResponseCode(200))

        val request = Request.Builder()
            .url(server.url("/test"))
            .addHeader("X-Custom", "value123")
            .build()

        client.newCall(request).execute()

        val recordedRequest = server.takeRequest()
        assertEquals("value123", recordedRequest.getHeader("X-Custom"))
        assertNotNull(recordedRequest.getHeader("Authorization"))
    }

    @Test
    fun `interceptor uses fresh token on each request`() {
        val apiKey = "abcdef1234567890:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"
        val interceptor = GhostAuthInterceptor { apiKey }

        val client = OkHttpClient.Builder()
            .addInterceptor(interceptor)
            .build()

        server.enqueue(MockResponse().setResponseCode(200))
        server.enqueue(MockResponse().setResponseCode(200))

        client.newCall(Request.Builder().url(server.url("/1")).build()).execute()
        val token1 = server.takeRequest().getHeader("Authorization")

        // Small delay to ensure different iat
        Thread.sleep(1100)

        client.newCall(Request.Builder().url(server.url("/2")).build()).execute()
        val token2 = server.takeRequest().getHeader("Authorization")

        // Tokens should differ because iat changes each second
        assertNotEquals("Tokens should be fresh each time", token1, token2)
    }
}
