package eu.darken.sdmse.appcleaner.core

import eu.darken.sdmse.appcleaner.core.forensics.ExpendablesFilter
import eu.darken.sdmse.appcleaner.core.forensics.ExpendablesFilterIdentifier
import eu.darken.sdmse.appcleaner.core.forensics.filter.DefaultCachesPublicFilter
import eu.darken.sdmse.appcleaner.core.scanner.InaccessibleCache
import eu.darken.sdmse.common.ca.CaString
import eu.darken.sdmse.common.ca.toCaString
import eu.darken.sdmse.common.pkgs.features.InstallId
import eu.darken.sdmse.common.pkgs.features.Installed
import eu.darken.sdmse.common.pkgs.isSystemApp
import eu.darken.sdmse.common.user.UserProfile2

data class AppJunk(
    val pkg: Installed,
    val userProfile: UserProfile2?,
    val expendables: Map<ExpendablesFilterIdentifier, Collection<ExpendablesFilter.Match>>?,
    val inaccessibleCache: InaccessibleCache?,
    val acsError: Exception? = null,
) {

    val identifier: InstallId
        get() = pkg.installId

    val label: CaString
        get() = pkg.label ?: pkg.packageName.toCaString()

    val isSystemApp: Boolean
        get() = pkg.isSystemApp

    val itemCount by lazy {
        var count = 0
        count += expendables?.values?.sumOf { it.size } ?: 0
        inaccessibleCache?.let { count += it.itemCount }
        count
    }

    val size by lazy {
        val knownFiles = expendables?.values?.flatten()?.sumOf { it.expectedGain } ?: 0L
        val inaccessibleSize = inaccessibleCache?.run {
            val publicCacheSize = expendables
                ?.get(DefaultCachesPublicFilter::class)
                ?.sumOf { it.expectedGain }
            when {
                publicCacheSize == null -> {
                    // No extra info about public caches
                    totalSize
                }

                publicSize != null -> {
                    // The system has seperate info for pub/priv caches
                    privateSize
                }

                else -> {
                    // Assume system info includes pub caches
                    totalSize - publicCacheSize
                }
            }
        } ?: 0L
        knownFiles + inaccessibleSize
    }

    fun isEmpty() =
        (expendables.isNullOrEmpty() || expendables.values.all { it.isEmpty() }) && inaccessibleCache == null

    override fun toString(): String =
        "AppJunk(${pkg.packageName}, categories=${expendables?.size}, inaccessible=$inaccessibleCache)"
}
