package com.tsmobile.app.data

import android.util.Log
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Request
import java.util.concurrent.TimeUnit

/**
 * Gitea 发布信息。
 */
data class ReleaseInfo(
    val versionName: String,
    val releaseUrl: String,
    val tagName: String,
    val body: String = "",
)

/**
 * GitHub/Gitea API 发布响应（部分字段）。
 */
@Serializable
private data class ReleaseResponse(
    val tag_name: String = "",
    val name: String = "",
    val html_url: String = "",
    val body: String = "",
)

/**
 * 更新检测器。
 *
 * 通过 Gitea REST API 获取最新发布的版本信息，
 * 用 semver 方式（x.y.z）与本地 versionName 比较判断是否有新版本。
 */
object UpdateChecker {

    private const val TAG = "UpdateChecker"

    /** Gitea 实例地址 */
    private const val GITEA_HOST = "rep.sansenhoshi.top"

    /** 仓库路径 */
    private const val REPO_PATH = "sansenhoshi/ts-mobile-go"

    /** Gitea API: 获取最新发布 */
    private val API_URL =
        "https://$GITEA_HOST/api/v1/repos/$REPO_PATH/releases/latest"

    private val json = Json { ignoreUnknownKeys = true }

    private val client: OkHttpClient by lazy {
        OkHttpClient.Builder()
            .connectTimeout(10, TimeUnit.SECONDS)
            .readTimeout(10, TimeUnit.SECONDS)
            .addInterceptor(UserAgentInterceptor())
            .build()
    }

    /**
     * 注入 User-Agent 头（Gitea API 建议携带）。
     */
    private class UserAgentInterceptor : Interceptor {
        override fun intercept(chain: Interceptor.Chain): okhttp3.Response {
            val request: Request = chain.request().newBuilder()
                .header("User-Agent", "TSMobile-UpdateChecker")
                .build()
            return chain.proceed(request)
        }
    }

    /**
     * 获取最新发布信息。
     *
     * @return [ReleaseInfo] 若成功获取并解析；null 表示请求失败或格式异常。
     */
    suspend fun fetchLatestRelease(): ReleaseInfo? = withContext(Dispatchers.IO) {
        try {
            val request = Request.Builder()
                .url(API_URL)
                .get()
                .build()

            val response = client.newCall(request).execute()

            if (!response.isSuccessful) {
                Log.w(TAG, "API returned ${response.code}: ${response.message}")
                response.close()
                return@withContext null
            }

            val body = response.body?.string() ?: run {
                response.close()
                return@withContext null
            }
            response.close()

            val release = json.decodeFromString<ReleaseResponse>(body)

            // 从 tag_name 解析版本号，失败则从 name 解析
            val versionName = parseVersionName(release.tag_name)
                ?: parseVersionName(release.name)
            if (versionName == null) {
                Log.w(TAG, "Cannot parse version from tag_name='${release.tag_name}' or name='${release.name}'")
                return@withContext null
            }

            Log.d(TAG, "Parsed release: version=$versionName, tag=${release.tag_name}, name=${release.name}")

            ReleaseInfo(
                versionName = versionName,
                releaseUrl = release.html_url.ifBlank {
                    "https://$GITEA_HOST/$REPO_PATH/releases"
                },
                tagName = release.tag_name,
                body = release.body,
            )
        } catch (e: Exception) {
            Log.w(TAG, "Failed to fetch latest release", e)
            null
        }
    }

    /**
     * 比较两个 semver 版本号。
     *
     * @return 正数表示 a > b，负数表示 a < b，0 表示相等。
     *
     * 示例：
     * - compareVersion("1.0.2", "1.0.0") → 1
     * - compareVersion("2.0.0", "1.9.9") → 1
     * - compareVersion("1.0.0", "1.0.0") → 0
     * - compareVersion("1.0", "1.0.0")  → -1
     */
    fun compareVersion(a: String, b: String): Int {
        val partsA = a.split(".").map { it.toIntOrNull() ?: 0 }
        val partsB = b.split(".").map { it.toIntOrNull() ?: 0 }
        val maxLen = maxOf(partsA.size, partsB.size)

        for (i in 0 until maxLen) {
            val numA = partsA.getOrElse(i) { 0 }
            val numB = partsB.getOrElse(i) { 0 }
            if (numA != numB) return numA - numB
        }
        return 0
    }

    /**
     * 从 tag_name 解析版本号（semver）。
     *
     * 支持格式：
     * - "v1.0.2" / "V1.0.2" → "1.0.2"
     * - "v2.0" → "2.0"
     * - "1.0.2" → "1.0.2"
     * - 无法解析则返回 null
     */
    private fun parseVersionName(tag: String): String? {
        if (tag.isBlank()) return null

        // 去掉前缀 v/V
        val version = tag.trimStart('v', 'V')

        // 提取数字和点号组成的版本段（如 "1.0.2"）
        val match = Regex("""^\d+(\.\d+)*""").find(version) ?: return null
        return match.value
    }
}
