package com.rssuper.parsing

import com.rssuper.models.Enclosure
import com.rssuper.models.Feed
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config

@RunWith(RobolectricTestRunner::class)
@Config(sdk = [24])
class RSSParserTest {

    @Test
    fun testParseBasicRSS() {
        val xml = """
            <?xml version="1.0" encoding="UTF-8"?>
            <rss version="2.0">
                <channel>
                    <title>Test Feed</title>
                    <link>https://example.com</link>
                    <description>A test feed</description>
                    <language>en-us</language>
                    <lastBuildDate>Mon, 01 Jan 2024 12:00:00 GMT</lastBuildDate>
                    <generator>RSS Generator</generator>
                    <ttl>60</ttl>
                    <item>
                        <title>Item 1</title>
                        <link>https://example.com/item1</link>
                        <description>Description of item 1</description>
                        <guid isPermaLink="true">https://example.com/item1</guid>
                        <pubDate>Mon, 01 Jan 2024 10:00:00 GMT</pubDate>
                    </item>
                    <item>
                        <title>Item 2</title>
                        <link>https://example.com/item2</link>
                        <description>Description of item 2</description>
                        <guid>item-2-guid</guid>
                        <pubDate>Sun, 31 Dec 2023 10:00:00 GMT</pubDate>
                    </item>
                </channel>
            </rss>
        """.trimIndent()

        val feed = RSSParser.parse(xml, "https://example.com/feed.xml")

        assertNotNull(feed)
        assertEquals("Test Feed", feed.title)
        assertEquals("https://example.com", feed.link)
        assertEquals("A test feed", feed.description)
        assertEquals("en-us", feed.language)
        assertEquals(60, feed.ttl)
        assertEquals(2, feed.items.size)

        val item1 = feed.items[0]
        assertEquals("Item 1", item1.title)
        assertEquals("https://example.com/item1", item1.link)
        assertEquals("Description of item 1", item1.description)
        assertNotNull(item1.published)
    }

    @Test
    fun testParseRSSWithiTunesNamespace() {
        val xml = """
            <?xml version="1.0" encoding="UTF-8"?>
            <rss version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd">
                <channel>
                    <title>Podcast Feed</title>
                    <link>https://example.com/podcast</link>
                    <description>My podcast</description>
                    <itunes:subtitle>Podcast subtitle</itunes:subtitle>
                    <itunes:author>Author Name</itunes:author>
                    <item>
                        <title>Episode 1</title>
                        <link>https://example.com/episode1</link>
                        <description>Episode description</description>
                        <itunes:duration>01:30:00</itunes:duration>
                        <enclosure url="https://example.com/ep1.mp3" type="audio/mpeg" length="12345678"/>
                    </item>
                </channel>
            </rss>
        """.trimIndent()

        val feed = RSSParser.parse(xml, "https://example.com/feed.xml")

        assertNotNull(feed)
        assertEquals("Podcast Feed", feed.title)

        val item = feed.items[0]
        assertEquals("Episode 1", item.title)
        assertNotNull(item.enclosure)
        assertEquals("https://example.com/ep1.mp3", item.enclosure?.url)
        assertEquals("audio/mpeg", item.enclosure?.type)
        assertEquals(12345678L, item.enclosure?.length)
    }

    @Test
    fun testParseRSSWithContentNamespace() {
        val xml = """
            <?xml version="1.0" encoding="UTF-8"?>
            <rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
                <channel>
                    <title>Feed with Content</title>
                    <item>
                        <title>Item with Content</title>
                        <description>Short description</description>
                        <content:encoded><![CDATA[<p>Full content here</p>]]></content:encoded>
                    </item>
                </channel>
            </rss>
        """.trimIndent()

        val feed = RSSParser.parse(xml, "https://example.com/feed.xml")

        assertNotNull(feed)
        assertEquals(1, feed.items.size)
        assertEquals("Item with Content", feed.items[0].title)
        assertEquals("<p>Full content here</p>", feed.items[0].content)
    }

    @Test
    fun testParseRSSWithCategories() {
        val xml = """
            <?xml version="1.0" encoding="UTF-8"?>
            <rss version="2.0">
                <channel>
                    <title>Categorized Feed</title>
                    <item>
                        <title>Tech Article</title>
                        <category>Technology</category>
                        <category>Programming</category>
                    </item>
                </channel>
            </rss>
        """.trimIndent()

        val feed = RSSParser.parse(xml, "https://example.com/feed.xml")

        assertNotNull(feed)
        val item = feed.items[0]
        assertEquals(2, item.categories?.size)
        assertEquals("Technology", item.categories?.get(0))
        assertEquals("Programming", item.categories?.get(1))
    }

    @Test
    fun testParseRSSWithAuthor() {
        val xml = """
            <?xml version="1.0" encoding="UTF-8"?>
            <rss version="2.0">
                <channel>
                    <title>Author Feed</title>
                    <item>
                        <title>Article by Author</title>
                        <author>author@example.com (John Doe)</author>
                    </item>
                </channel>
            </rss>
        """.trimIndent()

        val feed = RSSParser.parse(xml, "https://example.com/feed.xml")

        assertNotNull(feed)
        val item = feed.items[0]
        assertEquals("author@example.com (John Doe)", item.author)
    }

    @Test
    fun testParseRSSWithGuid() {
        val xml = """
            <?xml version="1.0" encoding="UTF-8"?>
            <rss version="2.0">
                <channel>
                    <title>Guid Feed</title>
                    <item>
                        <title>Item</title>
                        <guid>custom-guid-12345</guid>
                    </item>
                </channel>
            </rss>
        """.trimIndent()

        val feed = RSSParser.parse(xml, "https://example.com/feed.xml")

        assertNotNull(feed)
        assertEquals("custom-guid-12345", feed.items[0].guid)
    }

    @Test
    fun testParseRSSWithEmptyChannel() {
        val xml = """
            <?xml version="1.0" encoding="UTF-8"?>
            <rss version="2.0">
                <channel>
                    <title>Minimal Feed</title>
                </channel>
            </rss>
        """.trimIndent()

        val feed = RSSParser.parse(xml, "https://example.com/feed.xml")

        assertNotNull(feed)
        assertEquals("Minimal Feed", feed.title)
        assertEquals(0, feed.items.size)
    }

    @Test
    fun testParseRSSWithMissingFields() {
        val xml = """
            <?xml version="1.0" encoding="UTF-8"?>
            <rss version="2.0">
                <channel>
                    <item>
                        <title>Only Title</title>
                    </item>
                </channel>
            </rss>
        """.trimIndent()

        val feed = RSSParser.parse(xml, "https://example.com/feed.xml")

        assertNotNull(feed)
        assertEquals("Untitled Feed", feed.title)
        assertEquals(1, feed.items.size)
        assertEquals("Only Title", feed.items[0].title)
        assertNull(feed.items[0].link)
    }

    @Test
    fun testParseRSSWithCDATA() {
        val xml = """
            <?xml version="1.0" encoding="UTF-8"?>
            <rss version="2.0">
                <channel>
                    <title><![CDATA[CDATA Title]]></title>
                    <description><![CDATA[<p>HTML <strong>content</strong></p>]]></description>
                    <item>
                        <title>CDATA Item</title>
                        <description><![CDATA[Item content]]></description>
                    </item>
                </channel>
            </rss>
        """.trimIndent()

        val feed = RSSParser.parse(xml, "https://example.com/feed.xml")

        assertNotNull(feed)
        assertEquals("CDATA Title", feed.title)
        assertEquals("<p>HTML <strong>content</strong></p>", feed.description)
        assertEquals("Item content", feed.items[0].description)
    }
}
