package com.fabledsword.minstrel.player.output.upnp

import kotlinx.coroutines.test.runTest
import okhttp3.OkHttpClient
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertTrue

class RenderingControlClientTest {

    private lateinit var server: MockWebServer
    private lateinit var client: RenderingControlClient

    @BeforeEach
    fun setUp() {
        server = MockWebServer()
        server.start()
        client = RenderingControlClient(SoapClient(OkHttpClient()), server.url("/RC"))
    }

    @AfterEach
    fun tearDown() { server.shutdown() }

    @Test
    fun `getVolume parses CurrentVolume`() = runTest {
        server.enqueue(MockResponse().setBody(
            """<?xml version="1.0"?>
               <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
                 <s:Body>
                   <u:GetVolumeResponse xmlns:u="urn:schemas-upnp-org:service:RenderingControl:1">
                     <CurrentVolume>42</CurrentVolume>
                   </u:GetVolumeResponse>
                 </s:Body>
               </s:Envelope>""".trimIndent()))
        assertEquals(42, client.getVolume())
        val request = server.takeRequest()
        val body = request.body.readUtf8()
        assertTrue(body.contains("<Channel>Master</Channel>")) { body }
        assertEquals(
            "\"urn:schemas-upnp-org:service:RenderingControl:1#GetVolume\"",
            request.getHeader("SOAPACTION"),
        )
    }

    @Test
    fun `setVolume clamps and sends DesiredVolume`() = runTest {
        server.enqueue(MockResponse().setBody(
            """<?xml version="1.0"?>
               <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
                 <s:Body>
                   <u:SetVolumeResponse
                       xmlns:u="urn:schemas-upnp-org:service:RenderingControl:1"/>
                 </s:Body>
               </s:Envelope>""".trimIndent()))
        client.setVolume(150)
        val body = server.takeRequest().body.readUtf8()
        assertTrue(body.contains("<DesiredVolume>100</DesiredVolume>")) { body }
    }

    @Test
    fun `setVolume clamps below VOLUME_MIN to zero`() = runTest {
        server.enqueue(MockResponse().setBody(
            """<?xml version="1.0"?>
               <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
                 <s:Body>
                   <u:SetVolumeResponse
                       xmlns:u="urn:schemas-upnp-org:service:RenderingControl:1"/>
                 </s:Body>
               </s:Envelope>""".trimIndent()))
        client.setVolume(-5)
        val body = server.takeRequest().body.readUtf8()
        assertTrue(body.contains("<DesiredVolume>0</DesiredVolume>")) { body }
    }
}
