package com.erwan.revwatch.util

import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.drawable.Drawable
import android.os.Build
import org.xmlpull.v1.XmlPullParser

object IconPackHelper {

    data class IconPackInfo(val label: String, val packageName: String, val icon: Drawable)
    data class IconEntry(val name: String, val drawableId: Int)

    private val THEME_ACTIONS = listOf(
        "org.adw.launcher.THEMES",
        "com.novalauncher.THEME",
        "com.teslacoilsw.launcher.THEME",
        "com.fede.launcher.THEME_ICONPACK",
        "com.gau.go.launcherex.theme"
    )

    fun findInstalledPacks(ctx: Context): List<IconPackInfo> {
        val pm = ctx.packageManager
        val seen = mutableSetOf<String>()
        val packs = mutableListOf<IconPackInfo>()

        for (action in THEME_ACTIONS) {
            val intent = Intent(action)
            val infos = if (Build.VERSION.SDK_INT >= 33) {
                pm.queryIntentActivities(intent, PackageManager.ResolveInfoFlags.of(0))
            } else {
                @Suppress("DEPRECATION")
                pm.queryIntentActivities(intent, 0)
            }
            for (ri in infos) {
                val pkg = ri.activityInfo.packageName
                if (pkg in seen) continue
                seen.add(pkg)
                packs.add(
                    IconPackInfo(
                        label = ri.loadLabel(pm).toString(),
                        packageName = pkg,
                        icon = ri.loadIcon(pm)
                    )
                )
            }
        }
        return packs.sortedBy { it.label.lowercase() }
    }

    fun loadIcons(ctx: Context, iconPackPkg: String): List<IconEntry> {
        val res = try {
            ctx.packageManager.getResourcesForApplication(iconPackPkg)
        } catch (_: Exception) { return emptyList() }

        val entries = mutableListOf<IconEntry>()
        val seen = mutableSetOf<String>()

        val xmlId = res.getIdentifier("drawable", "xml", iconPackPkg)
        if (xmlId == 0) return entries

        try {
            val parser = res.getXml(xmlId)
            while (parser.next() != XmlPullParser.END_DOCUMENT) {
                if (parser.eventType == XmlPullParser.START_TAG && parser.name == "item") {
                    val drawableName = parser.getAttributeValue(null, "drawable") ?: continue
                    if (drawableName in seen) continue
                    seen.add(drawableName)
                    val drawableId = res.getIdentifier(drawableName, "drawable", iconPackPkg)
                    if (drawableId != 0) {
                        entries.add(IconEntry(drawableName, drawableId))
                    }
                }
            }
        } catch (_: Exception) {}

        return entries
    }

    /**
     * Parse appfilter.xml to find the drawable name mapped to a given app package.
     * Returns the first matching drawable name or null.
     */
    fun findSuggestedDrawable(ctx: Context, iconPackPkg: String, appPackage: String): String? {
        val res = try {
            ctx.packageManager.getResourcesForApplication(iconPackPkg)
        } catch (_: Exception) { return null }

        val xmlId = res.getIdentifier("appfilter", "xml", iconPackPkg)
        if (xmlId == 0) return null

        try {
            val parser = res.getXml(xmlId)
            while (parser.next() != XmlPullParser.END_DOCUMENT) {
                if (parser.eventType == XmlPullParser.START_TAG && parser.name == "item") {
                    val component = parser.getAttributeValue(null, "component") ?: continue
                    if (component.contains(appPackage)) {
                        val drawable = parser.getAttributeValue(null, "drawable")
                        if (!drawable.isNullOrBlank()) return drawable
                    }
                }
            }
        } catch (_: Exception) {}
        return null
    }

    fun loadDrawable(ctx: Context, iconPackPkg: String, drawableName: String): Drawable? {
        return try {
            val res = ctx.packageManager.getResourcesForApplication(iconPackPkg)
            val id = res.getIdentifier(drawableName, "drawable", iconPackPkg)
            if (id != 0) @Suppress("DEPRECATION") res.getDrawable(id, null) else null
        } catch (_: Exception) { null }
    }
}
