package ru.fincode.tsudesk.feature.news.data.remote.parser

import ru.fincode.tsudesk.feature.news.domain.model.NewsItem
import java.time.LocalDate
import java.time.format.DateTimeFormatter
import java.time.format.DateTimeParseException
import java.util.Locale

class NewsHtmlParser {

    private val dateFormatter =
        DateTimeFormatter.ofPattern("dd.MM.yyyy", Locale("ru"))

    fun parseArchivePage(html: String): List<NewsItem> {
        val itemRegex = Regex(
            pattern = """<div class="single-blog">([\s\S]*?)</div>\s*</div>\s*</div>""",
            options = setOf(RegexOption.IGNORE_CASE)
        )

        return itemRegex.findAll(html).mapNotNull { match ->
            val block = match.value

            val dateString = findFirst(
                block,
                """<span>\s*(\d{2}\.\d{2}\.\d{4})\s*</span>"""
            ) ?: return@mapNotNull null

            val date = parseDate(dateString) ?: return@mapNotNull null

            val category = findFirst(
                block,
                """</ul>\s*<span>\s*([^<]+?)\s*</span>"""
            )?.trim().orEmpty()

            val (url, title) = findLinkAndTitle(block) ?: return@mapNotNull null
            val id = extractIdFromUrl(url) ?: return@mapNotNull null

            NewsItem(
                id = id,
                title = htmlUnescape(title.trim()),
                url = url.trim(),
                date = date,
                category = htmlUnescape(category.trim())
            )
        }.toList()
    }

    private fun parseDate(raw: String): LocalDate? =
        try {
            LocalDate.parse(raw.trim(), dateFormatter)
        } catch (_: DateTimeParseException) {
            null
        }

    private fun findLinkAndTitle(block: String): Pair<String, String>? {
        val linkRegex = Regex(
            pattern = """<h3>\s*<a\s+href="([^"]+)">\s*([\s\S]*?)\s*</a>""",
            options = setOf(RegexOption.IGNORE_CASE)
        )
        val m = linkRegex.find(block) ?: return null
        val url = m.groupValues[1]
        val title = stripTags(m.groupValues[2])
        return url to title
    }

    private fun extractIdFromUrl(url: String): Long? {
        val idRegex = Regex(""".*/news/all/(\d+).*""")
        val m = idRegex.matchEntire(url) ?: return null
        return m.groupValues[1].toLongOrNull()
    }

    private fun findFirst(text: String, pattern: String): String? =
        Regex(pattern, RegexOption.IGNORE_CASE)
            .find(text)
            ?.groupValues
            ?.getOrNull(1)

    private fun stripTags(s: String): String =
        s.replace(Regex("<[^>]*>"), " ")
            .replace(Regex("\\s+"), " ")
            .trim()

    private fun htmlUnescape(s: String): String =
        s.replace("&quot;", "\"")
            .replace("&amp;", "&")
            .replace("&lt;", "<")
            .replace("&gt;", ">")
            .replace("&#39;", "'")
}