package com.ponzischeme89.memby.data

import com.ponzischeme89.memby.data.model.GatewayAlert
import com.ponzischeme89.memby.data.model.GatewayServiceStatus
import kotlinx.serialization.json.Json
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Test

class ServiceAlertTest {
    private val json = Json { ignoreUnknownKeys = true }

    private fun alert(id: String, title: String = "Northbound", message: String = "S02E04 aired") =
        GatewayAlert(id = id, kind = "sonarr-aired", title = title, message = message)

    @Test
    fun `picks the first alert this tv has not seen`() {
        val chosen = firstUnseenAlert(
            listOf(alert("a"), alert("b"), alert("c")),
            seen = setOf("a", "b"),
        )
        assertEquals("c", chosen?.id)
    }

    @Test
    fun `an alert already shown never comes back`() {
        assertNull(firstUnseenAlert(listOf(alert("a")), seen = setOf("a")))
    }

    @Test
    fun `incomplete alerts are dropped rather than drawn empty`() {
        val alerts = listOf(
            alert(id = ""),
            alert(id = "b", title = " "),
            alert(id = "c", message = ""),
            alert(id = "d"),
        )
        assertEquals("d", firstUnseenAlert(alerts, seen = emptySet())?.id)
    }

    @Test
    fun `an alert still on offer keeps waiting for a screen`() {
        assertFalse(
            pendingAlertExpired(
                pendingId = "a",
                shownId = null,
                alerts = listOf(alert("a"), alert("b")),
            ),
        )
    }

    @Test
    fun `an unshown alert is given up on once the gateway stops offering it`() {
        assertTrue(pendingAlertExpired(pendingId = "a", shownId = null, alerts = listOf(alert("b"))))
        assertTrue(pendingAlertExpired(pendingId = "a", shownId = null, alerts = emptyList()))
    }

    @Test
    fun `an alert already on screen is left to its own timer`() {
        assertFalse(pendingAlertExpired(pendingId = "a", shownId = "a", alerts = emptyList()))
    }

    @Test
    fun `status decodes without alerts for a gateway that predates them`() {
        val status = json.decodeFromString<GatewayServiceStatus>(
            """{"maintenance":false,"message":""}""",
        )
        assertTrue(status.alerts.isEmpty())
    }

    @Test
    fun `status decodes the alert payload the gateway sends`() {
        val status = json.decodeFromString<GatewayServiceStatus>(
            """
            {"maintenance":false,"message":"","alerts":[{
              "id":"sonarr:7:42:aired","kind":"sonarr-aired","title":"Northbound",
              "message":"S02E04 aired at 9:00 PM and will be in Emby soon.",
              "itemId":"sonarr:7:42","imageTag":"sonarr","airedAt":"2026-07-27T21:00:00+12:00"
            }]}
            """.trimIndent(),
        )
        val alert = status.alerts.single()
        assertEquals("sonarr:7:42:aired", alert.id)
        assertEquals("sonarr:7:42", alert.itemId)
        assertEquals("sonarr", alert.imageTag)
        // A gateway that predates server-worded banners sends no label at all.
        assertEquals("", alert.label)
    }

    @Test
    fun `status decodes a radarr import alert with its own wording`() {
        val status = json.decodeFromString<GatewayServiceStatus>(
            """
            {"maintenance":false,"message":"","alerts":[{
              "id":"radarr:412:file:9001","kind":"radarr-import","label":"NEW MOVIE ADDED",
              "title":"Mr. Smith Goes to Washington (1939)",
              "message":"Mr. Smith Goes to Washington will be available in Emby shortly.",
              "itemId":"radarr:412","imageTag":"radarr","airedAt":"2026-07-31T19:04:00Z"
            }]}
            """.trimIndent(),
        )
        val alert = status.alerts.single()
        assertEquals("radarr:412:file:9001", alert.id)
        assertEquals("NEW MOVIE ADDED", alert.label)
        // The image proxy serves Radarr covers under this pair, so the banner has a
        // poster before Emby has scanned the film in.
        assertEquals("radarr:412", alert.itemId)
        assertEquals("radarr", alert.imageTag)
    }
}
