package com.fmdxconnector

import android.app.AlertDialog
import android.content.Intent
import android.net.Uri
import android.util.Log
import androidx.activity.ComponentActivity
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.OkHttpClient
import okhttp3.Request
import java.util.Locale

object UpdateChecker {

    private const val TAG = "UpdateChecker"

    /**
     * Holt die Zielversion aus dem README, vergleicht sie mit currentVersion,
     * und zeigt bei neuer Version einen Dialog mit Download-Link.
     *
     * @return true, wenn ein Dialog angezeigt wurde; sonst false
     */
    suspend fun checkAndPrompt(activity: ComponentActivity, currentVersion: String): Boolean {
        return withContext(Dispatchers.IO) {
            try {
                val readmeText = fetchReadme() ?: return@withContext false
                val latest = extractVersionFromReadme(readmeText)?.let { cleanToken(it) } ?: return@withContext false
                val changes = extractChangesForVersion(readmeText, latest).orEmpty()
                val downloadUrl =
                    "https://github.com/Highpoint2000/FMDXConnector/raw/refs/heads/main/FMDXConnector_${latest}.apk"

                val cmp = compareVersions(normalizeForCompare(currentVersion), normalizeForCompare(latest))
                Log.d(TAG, "Current=$currentVersion, Latest=$latest, cmp=$cmp")

                if (cmp < 0) {
                    withContext(Dispatchers.Main) {
                        AlertDialog.Builder(activity)
                            .setTitle("Update available")
                            .setMessage(buildString {
                                append("A new version ($latest) is available.")
                                if (changes.isNotBlank()) {
                                    append("\n\nChanges:\n")
                                    append(changes)
                                }
                            })
                            .setPositiveButton("Download") { d, _ ->
                                runCatching {
                                    activity.startActivity(
                                        Intent(Intent.ACTION_VIEW, Uri.parse(downloadUrl))
                                    )
                                }
                                d.dismiss()
                            }
                            .setNegativeButton("Cancel", null)
                            .setCancelable(false)
                            .show()
                    }
                    true
                } else {
                    false
                }
            } catch (e: Exception) {
                Log.e(TAG, "Update check failed", e)
                false
            }
        }
    }

    // ---------------- intern: Netzwerk & Parsing ----------------

    private fun fetchReadme(): String? {
        val client = OkHttpClient()
        val req = Request.Builder()
            .url("https://raw.githubusercontent.com/Highpoint2000/FMDXConnector/refs/heads/main/README.md")
            .header("Cache-Control", "no-cache")
            .build()
        client.newCall(req).execute().use { resp ->
            if (!resp.isSuccessful) return null
            return resp.body?.string()
        }
    }

    private fun extractVersionFromReadme(text: String): String? {
        val primary = Regex("""(?im)^\s*#{0,6}\s*Version\s+(\d+(?:\.\d+)*(?:[._\-]?[A-Za-z0-9]+)*)""")
            .find(text)?.groupValues?.getOrNull(1)?.trim()
        if (!primary.isNullOrEmpty()) return primary
        return Regex("""\b\d+(?:\.\d+)*(?:[._\-]?[A-Za-z0-9]+)*\b""")
            .find(text)?.value?.trim()
    }

    private fun extractChangesForVersion(text: String, versionToken: String): String? {
        if (text.isEmpty() || versionToken.isBlank()) return null
        val versionLine = Regex("""(?im)^\s*#{0,6}\s*Version\s+${Regex.escape(versionToken)}\b.*$""")
            .find(text) ?: return null
        val startIdx = versionLine.range.last + 1
        if (startIdx >= text.length) return null

        val lines = text.substring(startIdx).lines()
        val sb = StringBuilder()
        var blanks = 0
        for (line in lines) {
            val t = line.trimEnd()
            if (t.isEmpty()) {
                blanks++
                if (sb.isNotEmpty() && blanks >= 1) break
                continue
            } else blanks = 0
            if (t.matches(Regex("""^#{1,6}\s+.*"""))) break
            sb.appendLine(t)
        }
        val raw = sb.toString().trim()
        if (raw.isEmpty()) return null
        val cleaned = raw.lines()
            .map { it.trim().trimStart('-', '*', '•', '‣', '◦').trim() }
            .filter { it.isNotEmpty() }
            .joinToString("\n") { "- $it" }
        return if (cleaned.length <= 1000) cleaned else cleaned.take(1000) + "\n…"
    }

    private fun cleanToken(token: String?): String? {
        if (token.isNullOrBlank()) return null
        var s = token.trim()
        val cuts = listOf(s.indexOf(" ("), s.indexOf(" \""), s.indexOf(" '"))
            .filter { it >= 0 }
        val cutIdx = cuts.minOrNull() ?: -1
        if (cutIdx >= 0) s = s.substring(0, cutIdx).trim()
        val parenIdx = s.indexOf('(')
        if (parenIdx >= 0) s = s.substring(0, parenIdx).trim()
        s = s.trim('*', '_', '`', '~', '"', '\'')
        s = s.replace(Regex("""\s+"""), "_")
        return s.takeIf { it.isNotBlank() }
    }

    private fun normalizeForCompare(v: String?): String {
        if (v.isNullOrBlank()) return "0"
        var s = v.trim()
        val idx = s.indexOf('(')
        if (idx >= 0) s = s.substring(0, idx).trim()
        return s.replace(Regex("""[_\- ]+"""), "").lowercase(Locale.ROOT)
    }

    /**
     * Vergleicht Versionen inkl. Sonderfall "3.74" → "3.7.4" und Prerelease-Ranking (alpha<beta<rc<stable)
     * Returns -1, 0, 1
     */
    private fun compareVersions(version1: String, version2: String): Int {
        fun parse(version: String): Pair<List<Int>, String?> {
            val trimmed = version.trim().lowercase(Locale.ROOT)
            val regex = Regex("""^(\d+(?:\.\d+)*)([a-z\-]+[\w\-]*)?$""")
            val m = regex.find(trimmed)
            var numbers: List<Int>
            var label: String? = null
            if (m != null) {
                val numsPart = m.groupValues[1]
                label = m.groupValues.getOrNull(2)?.takeIf { it.isNotEmpty() }
                numbers = numsPart.split(".").map { it.toIntOrNull() ?: 0 }
                // "3.74" → "3.7.4"
                if (numbers.size == 2 && numbers[1] > 9) {
                    val patch = numbers[1] % 10
                    val minor = numbers[1] / 10
                    numbers = listOf(numbers[0], minor, patch)
                }
            } else {
                numbers = listOf(0, 0, 0)
            }
            while (numbers.size < 3) numbers = numbers + 0
            return numbers to label
        }
        val (n1, l1) = parse(version1)
        val (n2, l2) = parse(version2)
        for (i in 0..2) {
            if (n1[i] < n2[i]) return -1
            if (n1[i] > n2[i]) return 1
        }
        fun rank(label: String?): Int = when {
            label == null -> 3
            label.startsWith("rc") -> 2
            label.startsWith("beta") -> 1
            label.startsWith("alpha") -> 0
            else -> -1
        }
        val r1 = rank(l1)
        val r2 = rank(l2)
        if (r1 != r2) return r1.compareTo(r2)
        if (l1 != null && l2 != null) return l1.compareTo(l2)
        return 0
    }
}
