package com.aletheia.app.data

import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test

class OpdsCatalogParserTest {
    @Test
    fun parsesFlibustaEntryAndPrefersEpubAcquisition() {
        val books = OpdsCatalogParser.parseBooks(SAMPLE_FEED) { href -> "http://m.flibusta.is$href" }

        assertEquals(1, books.size)
        val book = books.single()
        assertEquals("tag:book:123", book.id)
        assertEquals("Тестовая книга", book.title)
        assertEquals("Первый Автор, Второй Автор", book.author)
        assertEquals("epub", book.format)
        assertEquals("http://m.flibusta.is/b/123/epub", book.downloadUrl)
        assertEquals("http://m.flibusta.is/b/123", book.shareUrl)
        assertEquals("http://m.flibusta.is/i/23/123/cover.jpg", book.coverUrl)
        assertEquals("Описание книги Год издания: 2026", book.description)
        assertEquals("ru", book.language)
        assertEquals("2026", book.published)
    }

    @Test
    fun ignoresNavigationEntriesWithoutSupportedBookDownload() {
        val books = OpdsCatalogParser.parseBooks(NAVIGATION_FEED) { it }

        assertTrue(books.isEmpty())
    }

    @Test
    fun returnsResolvedNextPageEvenWhenSomeEntriesAreFilteredOut() {
        val page = OpdsCatalogParser.parsePage(PAGINATED_FEED) { href -> "https://books.example$href" }

        assertTrue(page.books.isEmpty())
        assertEquals("https://books.example/opds/search?pageNumber=2", page.nextPageUrl)
    }

    @Test
    fun recognizesFeedAndRejectsDoctype() {
        assertTrue(OpdsCatalogParser.isOpdsFeed(NAVIGATION_FEED))
        assertFalse(OpdsCatalogParser.isOpdsFeed("<!DOCTYPE feed><feed />"))
    }

    @Test
    fun removesSourceAttributionFromRemoteDescription() {
        val feed = SAMPLE_FEED.replace(
            "Описание книги",
            "Описание книги Флибуста https://m.flibusta.is/opds"
        )
        val description = OpdsCatalogParser.parseBooks(feed) { it }.single().description.orEmpty()

        assertFalse(description.contains("флибуста", ignoreCase = true))
        assertFalse(description.contains("flibusta", ignoreCase = true))
        assertFalse(description.contains("m.flibusta.is", ignoreCase = true))
    }

    @Test
    fun rewritesFlibustaHttpPort443RedirectToHttps() {
        val resolved = CatalogUrlResolver.resolveDownloadRedirect(
            sourceUrl = "http://m.flibusta.is/b/123/epub",
            location = "http://staticm.flibusta.is:443/converter/get/convert?out=epub&md5=abc"
        )

        assertEquals(
            "https://staticm.flibusta.is/converter/get/convert?out=epub&md5=abc",
            resolved
        )
    }

    private companion object {
        private val SAMPLE_FEED = """
            <?xml version="1.0" encoding="utf-8"?>
            <feed xmlns="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/terms/">
                <entry>
                    <id>tag:book:123</id>
                    <title>Тестовая книга</title>
                    <author><name>Первый Автор</name></author>
                    <author><name>Второй Автор</name></author>
                    <content type="text">Описание книги&lt;br/&gt;Год издания: 2026</content>
                    <dc:language>ru</dc:language>
                    <dc:issued>2026</dc:issued>
                    <link rel="http://opds-spec.org/image" type="image/jpeg" href="/i/23/123/cover.jpg" />
                    <link rel="http://opds-spec.org/acquisition/open-access" type="application/fb2+zip" href="/b/123/fb2" />
                    <link rel="http://opds-spec.org/acquisition/open-access" type="application/epub+zip" href="/b/123/epub" />
                    <link rel="alternate" type="text/html" href="/b/123" />
                </entry>
            </feed>
        """.trimIndent()

        private val NAVIGATION_FEED = """
            <?xml version="1.0" encoding="utf-8"?>
            <feed xmlns="http://www.w3.org/2005/Atom">
                <entry>
                    <id>tag:root:new</id>
                    <title>Новинки</title>
                    <link type="application/atom+xml;profile=opds-catalog" href="/opds/new" />
                </entry>
            </feed>
        """.trimIndent()

        private val PAGINATED_FEED = """
            <?xml version="1.0" encoding="utf-8"?>
            <feed xmlns="http://www.w3.org/2005/Atom">
                <link rel="next" href="/opds/search?pageNumber=2" />
                <entry>
                    <id>tag:root:new</id>
                    <title>Навигация</title>
                    <link type="application/atom+xml;profile=opds-catalog" href="/opds/new" />
                </entry>
            </feed>
        """.trimIndent()
    }
}
