package com.ponzischeme89.memby.data

import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.put
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Test

/**
 * The direct path's copy of the gateway's subtitle rule. It exists so the two agree — the
 * matching Go tests are in `server/internal/api/subtitles_test.go`, and the cases here are
 * deliberately the same ones.
 */
class SubtitlePreferenceTest {
    private fun track(
        id: String,
        language: String?,
        default: Boolean = false,
        forced: Boolean = false,
        hearingImpaired: Boolean = false,
    ) = SubtitleCandidate(id, language, default, forced, hearingImpaired)

    @Test
    fun `folds the codes Emby writes onto one vocabulary`() {
        assertEquals("it", normalizeSubtitleLanguage("ita"))
        assertEquals("it", normalizeSubtitleLanguage(" ITA "))
        assertEquals("fr", normalizeSubtitleLanguage("fra"))
        assertEquals("fr", normalizeSubtitleLanguage("fre"))
        assertEquals("pt", normalizeSubtitleLanguage("pt-BR"))
        assertEquals("", normalizeSubtitleLanguage(null))
        // An unrecognised code survives as itself, so an exact match still works.
        assertEquals("klingon", normalizeSubtitleLanguage("Klingon"))
    }

    @Test
    fun `subtitles turned off means nothing is selected`() {
        val tracks = listOf(track("1", "eng", default = true))
        assertNull(selectSubtitleId(tracks, enabled = false, language = "en"))
    }

    @Test
    fun `a chosen language takes the full track, not the forced or SDH one`() {
        val tracks = listOf(
            track("1", "eng", default = true),
            track("2", "ita", forced = true),
            track("3", "ita", hearingImpaired = true),
            track("4", "ita"),
        )

        assertEquals("4", selectSubtitleId(tracks, enabled = true, language = "it"))
    }

    @Test
    fun `a language the title does not have falls back to forced only`() {
        val withForced = listOf(
            track("1", "eng", default = true),
            track("2", "eng", forced = true),
        )
        assertEquals("2", selectSubtitleId(withForced, enabled = true, language = "it"))

        // Nothing rather than English, which the viewer did not ask for.
        val withoutForced = listOf(track("1", "eng", default = true))
        assertNull(selectSubtitleId(withoutForced, enabled = true, language = "it"))
    }

    @Test
    fun `no chosen language keeps the flag order an untouched install had`() {
        val tracks = listOf(
            track("1", "eng"),
            track("2", "eng", default = true),
            track("3", "eng", forced = true),
        )

        assertEquals("3", selectSubtitleId(tracks, enabled = true, SUBTITLE_LANGUAGE_AUTO))
        assertEquals("2", selectSubtitleId(tracks.take(2), enabled = true, language = ""))
        assertEquals("1", selectSubtitleId(tracks.take(1), enabled = true, SUBTITLE_LANGUAGE_AUTO))
        assertNull(selectSubtitleId(emptyList(), enabled = true, SUBTITLE_LANGUAGE_AUTO))
    }

    @Test
    fun `the choice rides the synced settings document`() {
        val local = UserPreferences(subtitlesEnabled = false, subtitleLanguage = "it")

        val encoded = local.encode()
        assertEquals(false, encoded["subtitlesEnabled"].toString().toBoolean())
        assertEquals(local, decodeUserPreferences(encoded))
    }

    @Test
    fun `a gateway that omits the keys leaves this TV's choice alone`() {
        // The whole point of the fallback: an older server growing the setting later must
        // not reset somebody who has already chosen one.
        val local = UserPreferences(subtitlesEnabled = false, subtitleLanguage = "it")

        val decoded = decodeUserPreferences(buildJsonObject { put("showTitleLogo", true) }, local)

        assertEquals(false, decoded.subtitlesEnabled)
        assertEquals("it", decoded.subtitleLanguage)
    }
}
