package com.aletheia.app.data

import java.net.URI
import java.util.Locale

object QBooksUrlPolicy {
    private val allowedCleartextHosts = setOf(
        "localhost",
        "127.0.0.1",
        "10.0.2.2",
        "192.168.0.185",
        "m.flibusta.is",
        "staticm.flibusta.is"
    )

    fun validate(url: String): Validation {
        val normalized = url.trim().trimEnd('/')
        if (normalized.isBlank()) {
            return Validation(Reason.Blank)
        }

        val uri = runCatching { URI(normalized) }.getOrNull()
            ?: return Validation(Reason.InvalidUri)
        val scheme = uri.scheme?.lowercase(Locale.US)
            ?: return Validation(Reason.InvalidUri)
        val host = uri.host?.normalizedHost()
            ?: return Validation(Reason.InvalidUri)

        if (scheme != "http" && scheme != "https") {
            return Validation(Reason.UnsupportedScheme)
        }

        if (scheme == "http" && !isAllowedCleartextHost(host)) {
            return Validation(Reason.ExternalCleartext)
        }

        return Validation(
            reason = Reason.Allowed,
            normalizedUrl = normalized,
            scheme = scheme,
            host = host
        )
    }

    fun normalizeBaseUrl(url: String): String {
        val validation = validate(url)
        require(validation.isAllowed) { validation.errorMessage }
        return validation.normalizedUrl.orEmpty()
    }

    fun isAllowed(url: String): Boolean = validate(url).isAllowed

    fun isHttps(url: String): Boolean = validate(url).scheme == "https"

    fun isAllowedCleartext(url: String): Boolean {
        val validation = validate(url)
        return validation.isAllowed && validation.scheme == "http"
    }

    private fun isAllowedCleartextHost(host: String): Boolean =
        host in allowedCleartextHosts || host == "local" || host.endsWith(".local")

    private fun String.normalizedHost(): String =
        trim()
            .removePrefix("[")
            .removeSuffix("]")
            .lowercase(Locale.US)

    data class Validation(
        val reason: Reason,
        val normalizedUrl: String? = null,
        val scheme: String? = null,
        val host: String? = null
    ) {
        val isAllowed: Boolean = reason == Reason.Allowed

        val errorMessage: String
            get() = when (reason) {
                Reason.Allowed -> ""
                Reason.Blank -> "Адрес каталога не задан"
                Reason.InvalidUri -> "Адрес каталога указан некорректно"
                Reason.UnsupportedScheme -> "Адрес каталога должен начинаться с http:// или https://"
                Reason.ExternalCleartext -> "Для внешнего каталога используйте HTTPS. HTTP разрешён только в локальной сети."
            }
    }

    enum class Reason {
        Allowed,
        Blank,
        InvalidUri,
        UnsupportedScheme,
        ExternalCleartext
    }
}
