package com.aryan.reader.tts

import android.speech.tts.Voice
import androidx.media3.common.util.UnstableApi
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import java.util.Locale

@androidx.annotation.OptIn(UnstableApi::class)
@RunWith(RobolectricTestRunner::class)
class TtsModePolicyTest {
    @Test
    fun `offline builds force device tts even when cloud config is present`() {
        val mode = resolveTtsModeForBuild(
            requestedModeName = TtsPlaybackManager.TtsMode.CLOUD.name,
            isOfflineBuild = true,
            isProBuild = true,
            workerUrl = "https://example.com/tts",
            byokCloudAvailable = true
        )

        assertEquals(TtsPlaybackManager.TtsMode.BASE, mode)
    }

    @Test
    fun `oss builds ignore server backed cloud tts without byok`() {
        val mode = resolveTtsModeForBuild(
            requestedModeName = TtsPlaybackManager.TtsMode.CLOUD.name,
            isOfflineBuild = false,
            isProBuild = false,
            workerUrl = "https://example.com/tts",
            byokCloudAvailable = false
        )

        assertEquals(TtsPlaybackManager.TtsMode.BASE, mode)
    }

    @Test
    fun `pro builds can use configured cloud tts`() {
        val mode = resolveTtsModeForBuild(
            requestedModeName = TtsPlaybackManager.TtsMode.CLOUD.name,
            isOfflineBuild = false,
            isProBuild = true,
            workerUrl = "https://example.com/tts",
            byokCloudAvailable = false
        )

        assertEquals(TtsPlaybackManager.TtsMode.CLOUD, mode)
    }

    @Test
    fun `oss builds can use byok cloud tts when online`() {
        val mode = resolveTtsModeForBuild(
            requestedModeName = TtsPlaybackManager.TtsMode.CLOUD.name,
            isOfflineBuild = false,
            isProBuild = false,
            workerUrl = "",
            byokCloudAvailable = true
        )

        assertEquals(TtsPlaybackManager.TtsMode.CLOUD, mode)
    }

    @Test
    fun `invalid tts mode falls back to device tts`() {
        val mode = resolveTtsModeForBuild(
            requestedModeName = "REMOTE",
            isOfflineBuild = false,
            isProBuild = true,
            workerUrl = "https://example.com/tts",
            byokCloudAvailable = false
        )

        assertEquals(TtsPlaybackManager.TtsMode.BASE, mode)
    }

    @Test
    fun `offline native tts ignores saved network voice`() {
        val localVoice = voice("local", requiresNetwork = false)
        val networkVoice = voice("network", requiresNetwork = true)

        val resolved = resolveNativeTtsVoiceForBuild(
            preferredVoiceName = networkVoice.name,
            defaultVoice = networkVoice,
            availableVoices = listOf(networkVoice, localVoice),
            defaultLocale = Locale.US,
            isOfflineBuild = true
        )

        assertEquals(localVoice.name, resolved?.name)
    }

    @Test
    fun `online native tts keeps saved network voice`() {
        val localVoice = voice("local", requiresNetwork = false)
        val networkVoice = voice("network", requiresNetwork = true)

        val resolved = resolveNativeTtsVoiceForBuild(
            preferredVoiceName = networkVoice.name,
            defaultVoice = localVoice,
            availableVoices = listOf(localVoice, networkVoice),
            defaultLocale = Locale.US,
            isOfflineBuild = false
        )

        assertEquals(networkVoice.name, resolved?.name)
    }

    private fun voice(
        name: String,
        locale: Locale = Locale.US,
        requiresNetwork: Boolean
    ): Voice {
        return Voice(
            name,
            locale,
            Voice.QUALITY_NORMAL,
            Voice.LATENCY_NORMAL,
            requiresNetwork,
            emptySet<String>()
        )
    }
}
