package com.ponzischeme89.memby.ui

import com.ponzischeme89.memby.data.HomeSnapshot
import com.ponzischeme89.memby.data.model.BaseItem
import com.ponzischeme89.memby.data.model.HomeRow
import com.ponzischeme89.memby.data.model.MyShow
import org.junit.Assert.assertFalse
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test

class AiringTodayTagsTest {
    @Test
    fun `continue watching promotes episodes from shows airing today`() {
        val ended = BaseItem(
            id = "ended", name = "Old episode", type = "Episode", seriesName = "Ended Rewatch",
        )
        val pausedMovie = BaseItem(id = "movie", name = "Paused Movie", type = "Movie")
        val airing = BaseItem(
            id = "airing", name = "New episode", type = "Episode", seriesName = "The Bear",
        )
        val home = HomeSnapshot(
            continueWatching = listOf(ended, pausedMovie, airing),
            rows = listOf(
                HomeRow(
                    id = "continue", title = "Continue Watching",
                    items = listOf(ended, pausedMovie, airing),
                ),
                HomeRow(
                    id = "sonarr-airing-today", title = "Shows airing today", kind = "schedule",
                    items = listOf(
                        BaseItem(
                            id = "sonarr:7:42", name = "The Bear", type = "MembySonarrEpisode",
                            membySource = "sonarr", membyAirDayLabel = "Today",
                        ),
                    ),
                ),
            ),
        )

        val ranked = home.withAiringTodayTags()

        assertEquals(listOf("airing", "ended", "movie"), ranked.continueWatching.map { it.id })
        assertEquals(listOf("airing", "ended", "movie"), ranked.rows.first().items.map { it.id })
        assertTrue(ranked.continueWatching.first().membyAiringToday)
        assertFalse(ranked.continueWatching[1].membyAiringToday)
    }

    @Test
    fun `tags matching recommended series from today's TV schedule`() {
        val home = HomeSnapshot(
            rows = listOf(
                HomeRow(
                    id = "sonarr-airing-today",
                    title = "Shows airing today",
                    kind = "schedule",
                    items = listOf(
                        BaseItem(
                            id = "sonarr:7:42",
                            name = "The Bear",
                            type = "MembySonarrEpisode",
                            membySource = "sonarr",
                            membyAirDayLabel = "Today",
                        ),
                    ),
                ),
                HomeRow(
                    id = "recommended",
                    title = "Recommended",
                    kind = "recommended",
                    items = listOf(
                        BaseItem(id = "series-1", name = "The Bear", type = "Series"),
                        BaseItem(id = "series-2", name = "Severance", type = "Series"),
                    ),
                ),
            ),
        )

        val recommendations = home.withAiringTodayTags().rows.last().items

        assertTrue(recommendations[0].membyAiringToday)
        assertFalse(recommendations[1].membyAiringToday)
    }

    @Test
    fun `show matching ignores punctuation spacing and case`() {
        val home = HomeSnapshot(
            rows = listOf(
                HomeRow(
                    id = "sonarr-airing-today",
                    title = "Shows airing today",
                    items = listOf(
                        BaseItem(
                            id = "sonarr:1:2",
                            name = "Marvel's DAREDEVIL",
                            type = "MembySonarrEpisode",
                            membySource = "sonarr",
                            membyAirDayLabel = "Today",
                        ),
                    ),
                ),
                HomeRow(
                    id = "recommended",
                    title = "Recommended",
                    items = listOf(
                        BaseItem(id = "series-1", name = "Marvels Daredevil", type = "Series"),
                    ),
                ),
            ),
        )

        assertTrue(home.withAiringTodayTags().rows.last().items.single().membyAiringToday)
    }

    @Test
    fun `does not tag movies with a matching title`() {
        val home = HomeSnapshot(
            rows = listOf(
                HomeRow(
                    id = "sonarr-airing-today",
                    title = "Shows airing today",
                    items = listOf(
                        BaseItem(
                            id = "sonarr:1:2",
                            name = "Fargo",
                            type = "MembySonarrEpisode",
                            membySource = "sonarr",
                            membyAirDayLabel = "Today",
                        ),
                    ),
                ),
                HomeRow(
                    id = "recommended",
                    title = "Recommended",
                    items = listOf(BaseItem(id = "movie-1", name = "Fargo", type = "Movie")),
                ),
            ),
        )

        assertFalse(home.withAiringTodayTags().rows.last().items.single().membyAiringToday)
    }

    @Test
    fun `only today's scheduled show is propagated to other rows`() {
        val home = HomeSnapshot(
            rows = listOf(
                HomeRow(
                    id = "sonarr-airing-today",
                    title = "Shows airing in the next 5 days",
                    kind = "schedule",
                    items = listOf(
                        BaseItem(
                            id = "sonarr:1:1",
                            name = "Today Show",
                            type = "MembySonarrEpisode",
                            membySource = "sonarr",
                            membyAirDayLabel = "Today",
                        ),
                        BaseItem(
                            id = "sonarr:2:1",
                            name = "Tomorrow Show",
                            type = "MembySonarrEpisode",
                            membySource = "sonarr",
                            membyAirDayLabel = "Tomorrow",
                        ),
                    ),
                ),
                HomeRow(
                    id = "recommended",
                    title = "Recommended",
                    items = listOf(
                        BaseItem(id = "series-1", name = "Today Show", type = "Series"),
                        BaseItem(id = "series-2", name = "Tomorrow Show", type = "Series"),
                    ),
                ),
            ),
        )

        val recommendations = home.withAiringTodayTags().rows.last().items
        assertTrue(recommendations[0].membyAiringToday)
        assertFalse(recommendations[1].membyAiringToday)
    }

    @Test
    fun `schedule poster badges use each server-authored day`() {
        fun scheduled(day: String) = BaseItem(
            id = day,
            name = "Show",
            type = "MembySonarrEpisode",
            membySource = "sonarr",
            membyAirDayLabel = day,
            membyAiringToday = true,
        )

        assertEquals("TODAY", airingBadgeLabel(scheduled("Today")))
        assertEquals("TOMORROW", airingBadgeLabel(scheduled("Tomorrow")))
        assertEquals("FRIDAY", airingBadgeLabel(scheduled("Friday")))
    }

    @Test
    fun `Radarr movie schedule uses its server-authored release day badge`() {
        val movie = BaseItem(
            id = "radarr:7",
            name = "Arrival",
            type = "MembyRadarrMovie",
            membySource = "radarr",
            membyAirDayLabel = "Saturday",
        )

        assertEquals("SATURDAY", airingBadgeLabel(movie))
    }

    @Test
    fun `upcoming schedule status leaves the air day unobstructed`() {
        assertEquals(null, scheduleStatusBadgeLabel("upcoming"))
        assertEquals(null, scheduleStatusBadgeLabel(""))
        assertEquals("DOWNLOADING", scheduleStatusBadgeLabel("downloading"))
    }

    @Test
    fun `a schedule card wears the lifecycle the gateway worded`() {
        fun card(lifecycle: String?, text: String?) = BaseItem(
            id = "sonarr:1:2", name = "Show", type = "MembySonarrEpisode",
            membySource = "sonarr", membyLifecycle = lifecycle, membyLifecycleText = text,
        )

        assertEquals("CONTINUING", lifecycleBadgeLabel(card("continuing", "CONTINUING")))
        assertEquals("IN CINEMAS", lifecycleBadgeLabel(card("incinemas", "IN CINEMAS")))
        // A status this build predates still reads correctly, because the wording is the
        // server's rather than derived from the slug.
        assertEquals("PILOT ORDERED", lifecycleBadgeLabel(card("pilot", "Pilot ordered")))
        // An older gateway, or a show *arr has no status for: no tag rather than a blank one.
        assertEquals(null, lifecycleBadgeLabel(card(null, null)))
        assertEquals(null, lifecycleBadgeLabel(card("continuing", "  ")))
    }

    @Test
    fun `a cancelled show outranks everything else on its My Shows card`() {
        val cancelled = MyShow(
            itemId = "1", title = "Ended Show", lifecycle = "Cancelled",
            sonarrStatus = "Monitored", nextEpisode = "2026-08-09T20:00:00Z",
        )

        // Red, and the same word Sonarr uses, is worth more than a next-episode date on a
        // show that will not have one.
        assertEquals("ended" to "CANCELLED", myShowBadge(cancelled))
    }

    @Test
    fun `a continuing show says so`() {
        val continuing = MyShow(
            itemId = "1", title = "Severance", lifecycle = "Continuing", sonarrStatus = "Monitored",
        )
        assertEquals("continuing" to "CONTINUING", myShowBadge(continuing))

        val dated = continuing.copy(nextEpisode = "2026-08-09T20:00:00Z")
        assertEquals("upcoming" to "UPCOMING", myShowBadge(dated))

        val unmonitored = continuing.copy(sonarrStatus = "Not monitored")
        assertEquals("unmonitored" to "UNMONITORED", myShowBadge(unmonitored))

        val unknown = continuing.copy(lifecycle = "Unknown", sonarrStatus = "Not found")
        assertEquals(null, myShowBadge(unknown))
    }
}
