package xyz.cottongin.radio247.metadata

import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import okhttp3.OkHttpClient
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Before
import org.junit.Test

@OptIn(ExperimentalCoroutinesApi::class)
class AlbumArtResolverTest {

    private lateinit var server: MockWebServer
    private lateinit var client: OkHttpClient
    private lateinit var resolver: AlbumArtResolver

    @Before
    fun setUp() {
        server = MockWebServer()
        server.start()

        val baseUrl = server.url("/").toString().trimEnd('/')
        client = OkHttpClient.Builder().build()
        resolver = AlbumArtResolver(
            client = client,
            artCache = ArtCache(maxSize = 100),
            musicBrainzBaseUrl = baseUrl,
            coverArtBaseUrl = baseUrl
        )
    }

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

    @Test
    fun returns_cached_url_on_cache_hit() = runTest {
        val artCache = ArtCache(maxSize = 100)
        artCache.put("Artist-Title", "https://cached.example/art.jpg")
        val r = AlbumArtResolver(client, artCache)

        val result = r.resolve(
            artist = "Artist",
            title = "Title",
            icyStreamUrl = null,
            stationArtworkUrl = null
        )

        assertEquals("https://cached.example/art.jpg", result)
    }

    @Test
    fun queries_musicbrainz_when_artist_and_title_present() = runTest {
        val mbJson = """
            {
                "recordings": [{
                    "id": "rec-123",
                    "releases": [{"id": "rel-456"}]
                }]
            }
        """.trimIndent()

        server.enqueue(
            MockResponse()
                .setBody(mbJson)
                .addHeader("Content-Type", "application/json")
        )

        val baseUrl = server.url("/").toString().trimEnd('/')
        val testResolver = AlbumArtResolver(
            client = client,
            musicBrainzBaseUrl = baseUrl,
            coverArtBaseUrl = baseUrl,
                skipArtVerification = true
        )

        val result = testResolver.resolve(
            artist = "Test Artist",
            title = "Test Title",
            icyStreamUrl = null,
            stationArtworkUrl = null
        )

        assertEquals("$baseUrl/release/rel-456/front-250", result)
    }

    @Test
    fun skips_musicbrainz_when_artist_is_null() = runTest {
        val result = resolver.resolve(
            artist = null,
            title = "Some Title",
            icyStreamUrl = null,
            stationArtworkUrl = "https://station.com/default.png"
        )

        assertEquals("https://station.com/default.png", result)
    }

    @Test
    fun skips_musicbrainz_when_title_is_null() = runTest {
        val result = resolver.resolve(
            artist = "Some Artist",
            title = null,
            icyStreamUrl = null,
            stationArtworkUrl = "https://station.com/art.png"
        )

        assertEquals("https://station.com/art.png", result)
    }

    @Test
    fun falls_through_to_icy_stream_url() = runTest {
        val result = resolver.resolve(
            artist = null,
            title = null,
            icyStreamUrl = "https://stream.example/cover.jpg",
            stationArtworkUrl = "https://station.com/fallback.png"
        )

        assertEquals("https://stream.example/cover.jpg", result)
    }

    @Test
    fun falls_through_to_station_artwork() = runTest {
        val result = resolver.resolve(
            artist = null,
            title = null,
            icyStreamUrl = null,
            stationArtworkUrl = "https://station.com/default.png"
        )

        assertEquals("https://station.com/default.png", result)
    }

    @Test
    fun returns_null_when_nothing_found() = runTest {
        val result = resolver.resolve(
            artist = null,
            title = null,
            icyStreamUrl = null,
            stationArtworkUrl = null
        )

        assertNull(result)
    }

    @Test
    fun icy_stream_url_must_look_like_image() = runTest {
        val result = resolver.resolve(
            artist = null,
            title = null,
            icyStreamUrl = "https://stream.example/audio.mp3",
            stationArtworkUrl = "https://station.com/default.png"
        )

        assertEquals("https://station.com/default.png", result)
    }

    @Test
    fun musicbrainz_empty_recordings_falls_through() = runTest {
        server.enqueue(
            MockResponse()
                .setBody("""{"recordings": []}""")
                .addHeader("Content-Type", "application/json")
        )

        val result = resolver.resolve(
            artist = "Unknown",
            title = "Unknown",
            icyStreamUrl = null,
            stationArtworkUrl = "https://station.com/default.png"
        )

        assertEquals("https://station.com/default.png", result)
    }
}
