package xyz.cottongin.radio247.service

import io.mockk.coEvery
import io.mockk.mockk
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
import org.junit.Test
import xyz.cottongin.radio247.data.db.StationPreferenceDao
import xyz.cottongin.radio247.data.db.StationStreamDao
import xyz.cottongin.radio247.data.model.Station
import xyz.cottongin.radio247.data.model.StationPreference
import xyz.cottongin.radio247.data.model.StationStream
import xyz.cottongin.radio247.data.prefs.RadioPreferences

class StreamResolverTest {

    private val streamDao = mockk<StationStreamDao>()
    private val prefs = mockk<RadioPreferences>()
    private val stationPrefDao = mockk<StationPreferenceDao>()

    private val testStation = Station(
        id = 1L,
        name = "Test",
        url = "http://fallback.com/stream"
    )

    @Test
    fun `returns station url when no streams exist`() = runTest {
        coEvery { streamDao.getStreamsForStation(1L) } returns emptyList()
        coEvery { stationPrefDao.getByStationId(any()) } returns null
        val resolver = StreamResolver(streamDao, prefs, stationPrefDao)
        val urls = resolver.resolveUrls(testStation)
        assertEquals(listOf("http://fallback.com/stream"), urls)
    }

    @Test
    fun `orders streams by quality preference`() = runTest {
        coEvery { streamDao.getStreamsForStation(1L) } returns listOf(
            StationStream(id = 1, stationId = 1, bitrate = 128, ssl = false, url = "http://128.com"),
            StationStream(id = 2, stationId = 1, bitrate = 256, ssl = true, url = "https://256.com"),
            StationStream(id = 3, stationId = 1, bitrate = 128, ssl = true, url = "https://128.com")
        )
        coEvery { stationPrefDao.getByStationId(any()) } returns null
        coEvery { prefs.qualityPreference } returns flowOf(StreamResolver.DEFAULT_ORDER_JSON)
        val resolver = StreamResolver(streamDao, prefs, stationPrefDao)
        val urls = resolver.resolveUrls(testStation)
        assertEquals("https://256.com", urls[0])
        assertEquals("https://128.com", urls[1])
        assertEquals("http://128.com", urls[2])
    }

    @Test
    fun `uses station qualityOverride when set`() = runTest {
        val stationWithOverride = testStation.copy(
            qualityOverride = """["128-ssl","128-nossl","256-ssl","256-nossl"]"""
        )
        coEvery { streamDao.getStreamsForStation(1L) } returns listOf(
            StationStream(id = 1, stationId = 1, bitrate = 128, ssl = false, url = "http://128.com"),
            StationStream(id = 2, stationId = 1, bitrate = 256, ssl = true, url = "https://256.com"),
            StationStream(id = 3, stationId = 1, bitrate = 128, ssl = true, url = "https://128.com")
        )
        coEvery { stationPrefDao.getByStationId(any()) } returns null
        val resolver = StreamResolver(streamDao, prefs, stationPrefDao)
        val urls = resolver.resolveUrls(stationWithOverride)
        assertEquals("https://128.com", urls[0])
        assertEquals("http://128.com", urls[1])
        assertEquals("https://256.com", urls[2])
    }

    @Test
    fun `stationPreference qualityOverride takes precedence over station field`() = runTest {
        coEvery { streamDao.getStreamsForStation(1L) } returns listOf(
            StationStream(id = 1, stationId = 1, bitrate = 128, ssl = true, url = "https://128.com"),
            StationStream(id = 2, stationId = 1, bitrate = 256, ssl = true, url = "https://256.com")
        )
        coEvery { stationPrefDao.getByStationId(1L) } returns StationPreference(
            stationId = 1L,
            qualityOverride = """["128-ssl","256-ssl"]"""
        )
        val stationWithOverride = testStation.copy(
            qualityOverride = """["256-ssl","128-ssl"]"""
        )
        val resolver = StreamResolver(streamDao, prefs, stationPrefDao)
        val urls = resolver.resolveUrls(stationWithOverride)
        assertEquals("https://128.com", urls[0])
    }
}
