package xyz.kusoft.argusupdater

data class ArgusUpdateConfig(
    val baseUrl: String,
    val slug: String,
    val platform: String = "android-universal",
    val channel: String = "stable"
)

data class ArgusInstalledApp(
    val packageName: String,
    val versionCode: Long,
    val versionName: String?
)

data class ArgusRelease(
    val id: String,
    val version: String,
    val channel: String,
    val platform: String,
    val packageKind: String,
    val androidVersionCode: Long?,
    val downloadPath: String,
    val originalFileName: String,
    val contentType: String,
    val packageSizeBytes: Long,
    val sha256: String,
    val publishedAt: String,
    val notes: String?
) {
    val resolvedVersionName: String
        get() = version.substringBefore('+').trim().ifBlank { version.trim() }

    val resolvedVersionCode: Long?
        get() = androidVersionCode?.takeIf { it > 0 }
            ?: version.substringAfterLast('+', missingDelimiterValue = "")
                .trim()
                .toLongOrNull()
                ?.takeIf { it > 0 }
            ?: parseVersionCodeFromFileName(originalFileName)

    companion object {
        private val VersionCodeFileNameRegex = Regex(
            """(?:^|[-_])(\d+)\.apk$""",
            RegexOption.IGNORE_CASE
        )

        fun parseVersionCodeFromFileName(fileName: String?): Long? {
            if (fileName.isNullOrBlank()) {
                return null
            }

            return VersionCodeFileNameRegex
                .find(fileName.trim())
                ?.groupValues
                ?.getOrNull(1)
                ?.toLongOrNull()
                ?.takeIf { it > 0 }
        }
    }
}

data class ArgusManifest(
    val slug: String,
    val name: String,
    val summary: String,
    val description: String,
    val androidPackageName: String?,
    val repositoryUrl: String?,
    val homepageUrl: String?,
    val release: ArgusRelease
)

data class ArgusAvailableUpdate(
    val config: ArgusUpdateConfig,
    val installedApp: ArgusInstalledApp,
    val manifest: ArgusManifest
) {
    val versionCode: Long
        get() = manifest.release.resolvedVersionCode ?: 0L

    val downloadUrl: String
        get() {
            val rawPath = manifest.release.downloadPath.trim()
            if (rawPath.startsWith("http://", ignoreCase = true) ||
                rawPath.startsWith("https://", ignoreCase = true)
            ) {
                return rawPath
            }

            return config.baseUrl.trimEnd('/') + "/" + rawPath.trimStart('/')
        }
}

sealed interface ArgusUpdateCheckResult {
    data class NotPublished(val reason: String) : ArgusUpdateCheckResult

    data class UpToDate(val manifest: ArgusManifest?) : ArgusUpdateCheckResult

    data class UpdateAvailable(val update: ArgusAvailableUpdate) : ArgusUpdateCheckResult

    data class Incompatible(val reason: String) : ArgusUpdateCheckResult

    data class Failed(val reason: String, val cause: Throwable? = null) : ArgusUpdateCheckResult
}

sealed interface ArgusInstallSubmissionResult {
    data class Submitted(val message: String) : ArgusInstallSubmissionResult

    data class Rejected(val message: String) : ArgusInstallSubmissionResult
}

data class ArgusInstallerEvent(
    val state: String,
    val packageName: String?,
    val releaseVersion: String?,
    val versionCode: Long?,
    val detail: String?,
    val updatedAtEpochMillis: Long
)

object ArgusInstallerEventState {
    const val Submitted = "submitted"
    const val ApprovalRequired = "approval_required"
    const val Installed = "installed"
    const val Failed = "failed"
}
