package io.github.chinosk.gakumas.localify.hookUtils

import android.util.Log
import java.io.BufferedReader
import java.io.File
import java.io.IOException
import java.io.InputStream
import java.io.InputStreamReader
import java.util.zip.ZipFile

object FilesChecker {
    private const val MODULE_ASSETS_PREFIX = "assets/"

    lateinit var filesDir: File
    lateinit var modulePath: String
    val localizationFilesDir = "gakumas-local"
    var filesUpdated = false

    fun initAndCheck(fileDir: File, modulePath: String) {
        initDir(fileDir, modulePath)
        checkFiles()
    }

    fun initDir(fileDir: File, modulePath: String) {
        this.filesDir = fileDir
        this.modulePath = modulePath
    }

    fun checkFiles() {
        val installedVersion = getInstalledVersion()
        val pluginVersion = getPluginVersion()
        Log.d("GakumasLocal", "installedVer: $installedVersion, pluginVer: $pluginVersion")

        if (pluginVersion != installedVersion) {
            updateFiles()
        }
    }

    fun updateFiles() {
        if (filesUpdated) return
        filesUpdated = true

        Log.i("GakumasLocal", "Updating files...")
        val pluginBasePath = File(filesDir, localizationFilesDir)
        if (!pluginBasePath.exists()) {
            pluginBasePath.mkdirs()
        }

        val rootAssetDir = moduleAssetPath(localizationFilesDir).trimEnd('/') + "/"
        ZipFile(modulePath).use { zipFile ->
            val entries = zipFile.entries()
            while (entries.hasMoreElements()) {
                val entry = entries.nextElement()
                val name = entry.name
                if (!name.startsWith(rootAssetDir)) continue

                val relativePath = name.removePrefix(MODULE_ASSETS_PREFIX)
                if (relativePath.isBlank()) continue

                val outFile = File(filesDir, relativePath)
                if (entry.isDirectory) {
                    outFile.mkdirs()
                    continue
                }

                outFile.parentFile?.mkdirs()
                zipFile.getInputStream(entry).use { input ->
                    outFile.outputStream().use { output ->
                        input.copyTo(output)
                    }
                }
            }
        }

        Log.i("GakumasLocal", "Updated")
    }

    fun getPluginVersion(): String {
        val versionAssetPath = moduleAssetPath("$localizationFilesDir/version.txt")
        ZipFile(modulePath).use { zipFile ->
            val entry = zipFile.getEntry(versionAssetPath) ?: return "0.0"
            zipFile.getInputStream(entry).use { stream ->
                return convertToString(stream).trim()
            }
        }
    }

    fun getInstalledVersion(): String {
        val pluginFilesDir = File(filesDir, localizationFilesDir)
        if (!pluginFilesDir.exists()) return "0.0"

        val versionFile = File(pluginFilesDir, "version.txt")
        if (!versionFile.exists()) return "0.0"
        return versionFile.readText().trim()
    }

    fun convertToString(inputStream: InputStream?): String {
        if (inputStream == null) return ""
        return try {
            BufferedReader(InputStreamReader(inputStream)).use { reader ->
                buildString {
                    var line: String?
                    while (reader.readLine().also { line = it } != null) {
                        append(line)
                    }
                }
            }
        } catch (e: IOException) {
            e.printStackTrace()
            ""
        }
    }

    private fun moduleAssetPath(path: String): String {
        val cleanPath = path.trimStart('/')
        return "$MODULE_ASSETS_PREFIX$cleanPath"
    }

    private fun deleteRecursively(file: File): Boolean {
        if (file.isDirectory) {
            val children = file.listFiles()
            if (children != null) {
                for (child in children) {
                    val success = deleteRecursively(child)
                    if (!success) {
                        return false
                    }
                }
            }
        }
        return file.delete()
    }

    fun cleanAssets() {
        val pluginBasePath = File(filesDir, localizationFilesDir)
        val localFilesDir = File(pluginBasePath, "local-files")

        val fontFile = File(localFilesDir, "gkamsZHFontMIX.otf")
        val resourceDir = File(localFilesDir, "resource")
        val genericTransDir = File(localFilesDir, "genericTrans")
        val genericTransFile = File(localFilesDir, "generic.json")
        val i18nFile = File(localFilesDir, "localization.json")
        val masterTransDir = File(localFilesDir, "masterTrans")

        if (fontFile.exists()) {
            fontFile.delete()
        }
        if (deleteRecursively(resourceDir)) {
            resourceDir.mkdirs()
        }
        if (deleteRecursively(genericTransDir)) {
            genericTransDir.mkdirs()
        }
        if (deleteRecursively(masterTransDir)) {
            masterTransDir.mkdirs()
        }
        if (genericTransFile.exists()) {
            genericTransFile.writeText("{}")
        }
        if (i18nFile.exists()) {
            i18nFile.writeText("{}")
        }
    }
}
