"""Tests for the DLNAClient SOAP and DIDL-Lite parsers."""

from r36s_dlna_browser.dlna.client import _extract_browse_result, _parse_didl
from r36s_dlna_browser.dlna.models import ItemType


_SAMPLE_DIDL = """\
<DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"
           xmlns:dc="http://purl.org/dc/elements/1.1/"
           xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/">
  <container id="1" parentID="0" childCount="3">
    <dc:title>Music</dc:title>
    <upnp:class>object.container.storageFolder</upnp:class>
  </container>
  <item id="100" parentID="1">
    <dc:title>Song.mp3</dc:title>
    <upnp:class>object.item.audioItem.musicTrack</upnp:class>
    <upnp:albumArtURI>http://srv/art.jpg</upnp:albumArtURI>
    <res protocolInfo="http-get:*:audio/mpeg:*" size="4000000" duration="0:03:21">http://srv/song.mp3</res>
  </item>
  <item id="200" parentID="1">
    <dc:title>Video.mkv</dc:title>
    <upnp:class>object.item.videoItem</upnp:class>
    <res protocolInfo="http-get:*:video/x-matroska:*">http://srv/video.mkv</res>
  </item>
</DIDL-Lite>
"""


class TestParseDIDL:
    def test_parses_container(self):
        items = _parse_didl(_SAMPLE_DIDL, "http://srv")
        containers = [i for i in items if i.is_container]
        assert len(containers) == 1
        assert containers[0].title == "Music"
        assert containers[0].child_count == 3

    def test_parses_audio_item(self):
        items = _parse_didl(_SAMPLE_DIDL, "http://srv")
        audio = [i for i in items if i.item_type == ItemType.AUDIO]
        assert len(audio) == 1
        assert audio[0].title == "Song.mp3"
        assert audio[0].resource_url == "http://srv/song.mp3"
        assert audio[0].mime_type == "audio/mpeg"
        assert audio[0].size == 4000000
        assert audio[0].duration == "0:03:21"
        assert audio[0].album_art_url == "http://srv/art.jpg"

    def test_parses_video_item(self):
        items = _parse_didl(_SAMPLE_DIDL, "http://srv")
        video = [i for i in items if i.item_type == ItemType.VIDEO]
        assert len(video) == 1
        assert video[0].title == "Video.mkv"
        assert "video/x-matroska" in video[0].mime_type

    def test_total_count(self):
        items = _parse_didl(_SAMPLE_DIDL, "http://srv")
        assert len(items) == 3

    def test_empty_didl(self):
        empty = '<DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"></DIDL-Lite>'
        assert _parse_didl(empty, "http://srv") == []

    def test_malformed_xml(self):
        assert _parse_didl("<<<not xml>>>", "http://srv") == []

    def test_relative_url_resolution(self):
        didl = """\
<DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"
           xmlns:dc="http://purl.org/dc/elements/1.1/"
           xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/">
  <item id="300" parentID="1">
    <dc:title>Relative</dc:title>
    <upnp:class>object.item.audioItem</upnp:class>
    <res protocolInfo="http-get:*:audio/flac:*">media/track.flac</res>
  </item>
</DIDL-Lite>
"""
        items = _parse_didl(didl, "http://myserver:8200")
        assert items[0].resource_url == "http://myserver:8200/media/track.flac"

    def test_prefers_video_resource_over_subtitle_resource(self):
        didl = """\
<DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"
           xmlns:dc="http://purl.org/dc/elements/1.1/"
           xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/">
  <item id="400" parentID="1">
    <dc:title>Movie</dc:title>
    <upnp:class>object.item.videoItem</upnp:class>
    <res protocolInfo="http-get:*:text/vtt:*">http://srv/movie.vtt</res>
    <res protocolInfo="http-get:*:video/x-matroska:*" size="999">http://srv/movie.mkv</res>
  </item>
</DIDL-Lite>
"""
        items = _parse_didl(didl, "http://srv")
        assert items[0].resource_url == "http://srv/movie.mkv"
        assert items[0].mime_type == "video/x-matroska"


class TestExtractBrowseResult:
    def test_extracts_unnamespaced_result(self):
        soap = """\
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <u:BrowseResponse xmlns:u="urn:schemas-upnp-org:service:ContentDirectory:1">
      <Result>&lt;DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"&gt;&lt;container id="1" parentID="0" /&gt;&lt;/DIDL-Lite&gt;</Result>
    </u:BrowseResponse>
  </s:Body>
</s:Envelope>
"""
        result = _extract_browse_result(soap)
        assert result is not None
        assert "DIDL-Lite" in result
        assert 'container id="1"' in result

    def test_extracts_namespaced_result(self):
        soap = """\
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="urn:schemas-upnp-org:service:ContentDirectory:1">
  <s:Body>
    <u:BrowseResponse>
      <u:Result>&lt;DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"&gt;&lt;/DIDL-Lite&gt;</u:Result>
    </u:BrowseResponse>
  </s:Body>
</s:Envelope>
"""
        assert _extract_browse_result(soap) is not None

    def test_extracts_embedded_xml_result(self):
        soap = """\
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <BrowseResponse>
      <Result>
        <DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/">
          <container id="1" parentID="0" />
        </DIDL-Lite>
      </Result>
    </BrowseResponse>
  </s:Body>
</s:Envelope>
"""
        result = _extract_browse_result(soap)
        assert result is not None
        assert "DIDL-Lite" in result

    def test_returns_none_when_missing(self):
        soap = "<Envelope><Body><BrowseResponse /></Body></Envelope>"
        assert _extract_browse_result(soap) is None
