package com.fabledsword.minstrel.update.data

import com.fabledsword.minstrel.models.UpdateInfo
import com.fabledsword.minstrel.models.wire.UpdateInfoWire
import com.fabledsword.minstrel.update.api.ClientVersionApi
import retrofit2.Retrofit
import javax.inject.Inject
import javax.inject.Singleton

/**
 * Thin facade over `/api/client/version`. Reused by the About card
 * (Check for updates button) and — in a follow-up — a startup
 * version banner.
 */
@Singleton
class UpdateRepository @Inject constructor(retrofit: Retrofit) {
    private val api: ClientVersionApi = retrofit.create(ClientVersionApi::class.java)

    suspend fun getLatest(): UpdateInfo = api.getVersion().toDomain()
}

private fun UpdateInfoWire.toDomain(): UpdateInfo = UpdateInfo(
    version = version,
    apkUrl = apkUrl,
    sizeBytes = sizeBytes,
)

/**
 * True when [server] is strictly newer than [installed]. Mirrors
 * Flutter's `isVersionNewer` — splits both strings on `.`, parses
 * each component as an int (non-numeric = 0), pads the shorter list
 * with zeros, then compares component-wise. Handles our date-style
 * versions (2026.05.10.1) which exceed semver's three-part shape,
 * and treats "2026.05.10" as equal to "2026.05.10.0".
 *
 * Falls back to string inequality when neither side parsed any
 * non-zero component (branch-name builds like "main" vs "dev") so
 * a dev build still gets the banner.
 */
fun isVersionNewer(server: String, installed: String): Boolean {
    val svr = parseVersion(server)
    val ins = parseVersion(installed)
    if (svr.all { it == 0 } && ins.all { it == 0 }) {
        return server.removePrefix("v") != installed.removePrefix("v")
    }
    val n = maxOf(svr.size, ins.size)
    val svrPadded = svr + List(n - svr.size) { 0 }
    val insPadded = ins + List(n - ins.size) { 0 }
    return compareComponentWise(svrPadded, insPadded)
}

private fun parseVersion(v: String): List<Int> =
    v.removePrefix("v").split('.').map { it.toIntOrNull() ?: 0 }

private fun compareComponentWise(svr: List<Int>, ins: List<Int>): Boolean =
    svr.zip(ins)
        .firstOrNull { (a, b) -> a != b }
        ?.let { (a, b) -> a > b }
        ?: false
