package com.xyzshell.andinfo.libs

import android.content.Context
import java.io.File

/**
 * 内存信息数据类
 * 包含设备的完整内存信息
 */
data class MemoryInfo(
    val totalRam: Long,          // 总内存 (字节)
    val availableRam: Long,      // 可用内存 (字节)
    val usedRam: Long,           // 已使用内存 (字节)
    val memType: String,         // 内存类型 (LPDDR4/LPDDR5/LPDDR5X等)
    val channels: Int,           // 内存通道数 (1/2/4)
    val zramTotal: Long,         // zram 总大小 (字节)
    val zramUsed: Long           // zram 已使用 (字节)
)

/**
 * 内存信息工具类
 * 提供内存相关的详细信息，包括总内存、可用内存、内存类型、通道数、ZRAM等
 */
class MemInfo(private val context: Context){

    /**
     * 获取完整的内存信息
     * @return MemoryInfo 包含所有内存相关信息的数据对象
     */
    fun getMemoryInfo(): MemoryInfo {
        val totalRam = getTotalMemory()
        val availableRam = getAvailableMemory()
        val usedRam = totalRam - availableRam
        val memType = getMemoryType()
        val channels = getMemoryChannels()
        val (zramTotal, zramUsed) = getZramInfo()

        return MemoryInfo(
            totalRam = totalRam,
            availableRam = availableRam,
            usedRam = usedRam,
            memType = memType,
            channels = channels,
            zramTotal = zramTotal,
            zramUsed = zramUsed
        )
    }

    /**
     * 获取总内存大小
     * 从 /proc/meminfo 读取 MemTotal 值
     * @return 总内存字节数
     */
    private fun getTotalMemory(): Long {
        return try {
            val memInfo = File("/proc/meminfo")
            memInfo.readLines().find { it.startsWith("MemTotal:") }?.let {
                it.split("\\s+".toRegex())[1].toLong() * 1024
            } ?: 0L
        } catch (e: Exception) {
            0L
        }
    }

    /**
     * 获取可用内存大小
     * 从 /proc/meminfo 读取 MemAvailable 值
     * @return 可用内存字节数
     */
    private fun getAvailableMemory(): Long {
        return try {
            val memInfo = File("/proc/meminfo")
            memInfo.readLines().find { it.startsWith("MemAvailable:") }?.let {
                it.split("\\s+".toRegex())[1].toLong() * 1024
            } ?: 0L
        } catch (e: Exception) {
            0L
        }
    }

    /**
     * 获取内存类型（LPDDR4、LPDDR4X、LPDDR5、LPDDR5X等）
     * 通过多种方式检测内存类型
     */
    private fun getMemoryType(): String {
        return try {
            // 1. 尝试从系统属性获取
            val propResult = getMemoryTypeFromProps()
            if (propResult != "Unknown") return propResult

            // 2. 尝试从 sysfs 设备文件获取
            val sysfsResult = getMemoryTypeFromSysfs()
            if (sysfsResult != "Unknown") return sysfsResult

            // 3. 尝试从设备树获取
            val deviceTreeResult = getMemoryTypeFromDeviceTree()
            if (deviceTreeResult != "Unknown") return deviceTreeResult

            // 4. 尝试从内核日志获取
            val dmesgResult = getMemoryTypeFromDmesg()
            if (dmesgResult != "Unknown") return dmesgResult

            // 5. 根据 Android 版本和设备信息推测
            val estimatedType = estimateMemoryType()
            if (estimatedType != "Unknown") return estimatedType

            "Unknown"
        } catch (e: Exception) {
            "Unknown"
        }
    }

    /**
     * 从系统属性获取内存类型
     */
    private fun getMemoryTypeFromProps(): String {
        val propKeys = listOf(
            "ro.boot.ddr_type",
            "ro.boot.ddrtype",
            "ro.boot.em.ddr_type",
            "ro.vendor.boot.ddr_type",
            "ro.product.vendor.boot.ddr_type",
            "persist.vendor.ddr.type",
            "vendor.boot.ddr.type"
        )

        for (key in propKeys) {
            try {
                val result = Runtime.getRuntime()
                    .exec(arrayOf("getprop", key))
                    .inputStream.bufferedReader().readText().trim()

                if (result.isNotEmpty() && result != "Unknown") {
                    return parseMemoryType(result)
                }
            } catch (e: Exception) {
                continue
            }
        }
        return "Unknown"
    }

    /**
     * 从 sysfs 文件系统获取内存类型
     */
    private fun getMemoryTypeFromSysfs(): String {
        val paths = listOf(
            // Qualcomm 设备
            "/sys/class/devfreq/soc:qcom,cpu-cpu-llcc-bw/device/type",
            "/sys/class/devfreq/soc:qcom,cpu-llcc-ddr-bw/device/type",
            "/sys/class/devfreq/ddrfreq/device/type",
            "/sys/devices/platform/soc/soc:qcom,cpu-cpu-llcc-bw/devfreq/*/type",
            "/sys/kernel/debug/clk/measure_only_mccc_clk/measure",

            // MediaTek 设备
            "/sys/kernel/debug/emi_mbw/dram_type",
            "/sys/devices/platform/soc/10012000.dvfsrc/helio-dvfsrc/dvfsrc_dump",

            // Samsung Exynos 设备
            "/sys/class/devfreq/17000010.devfreq_mif/device/type",
            "/sys/devices/platform/17000010.devfreq_mif/devfreq/devfreq0/type",

            // 通用路径
            "/proc/device-tree/memory/device_type",
            "/sys/firmware/devicetree/base/memory/device_type"
        )

        for (path in paths) {
            try {
                val file = File(path)
                if (file.exists() && file.canRead()) {
                    val content = file.readText().trim()
                    if (content.isNotEmpty()) {
                        val parsed = parseMemoryType(content)
                        if (parsed != "Unknown") return parsed
                    }
                }
            } catch (e: Exception) {
                continue
            }
        }
        return "Unknown"
    }

    /**
     * 从设备树获取内存类型
     */
    private fun getMemoryTypeFromDeviceTree(): String {
        val dtPaths = listOf(
            "/proc/device-tree/memory/ddr-type",
            "/proc/device-tree/memory@*/ddr-type",
            "/sys/firmware/devicetree/base/memory/ddr-type",
            "/sys/firmware/devicetree/base/memory@*/ddr-type"
        )

        for (path in dtPaths) {
            try {
                if (path.contains("*")) {
                    // 处理通配符路径
                    val parent = File(path.substringBeforeLast("/"))
                    if (parent.exists()) {
                        parent.listFiles()?.forEach { file ->
                            if (file.name.startsWith("memory") && File(file, "ddr-type").exists()) {
                                val content = File(file, "ddr-type").readText().trim()
                                val parsed = parseMemoryType(content)
                                if (parsed != "Unknown") return parsed
                            }
                        }
                    }
                } else {
                    val file = File(path)
                    if (file.exists()) {
                        val content = file.readText().trim()
                        val parsed = parseMemoryType(content)
                        if (parsed != "Unknown") return parsed
                    }
                }
            } catch (e: Exception) {
                continue
            }
        }
        return "Unknown"
    }

    /**
     * 从内核日志获取内存类型
     */
    private fun getMemoryTypeFromDmesg(): String {
        try {
            val dmesg = Runtime.getRuntime()
                .exec(arrayOf("sh", "-c", "dmesg | grep -iE 'ddr|lpddr|memory.*type'"))
                .inputStream.bufferedReader().readText()

            return parseMemoryType(dmesg)
        } catch (e: Exception) {
            return "Unknown"
        }
    }

    /**
     * 解析内存类型字符串，提取标准化的内存类型
     */
    private fun parseMemoryType(input: String): String {
        val normalized = input.uppercase()

        return when {
            // LPDDR5X
            normalized.contains("LPDDR5X") ||
            normalized.contains("LPDDR5-X") ||
            normalized.contains("LP5X") -> "LPDDR5X"

            // LPDDR5
            normalized.contains("LPDDR5") ||
            normalized.contains("LP5") ||
            normalized.contains("DDR5") && normalized.contains("LP") -> "LPDDR5"

            // LPDDR4X
            normalized.contains("LPDDR4X") ||
            normalized.contains("LPDDR4-X") ||
            normalized.contains("LP4X") -> "LPDDR4X"

            // LPDDR4
            normalized.contains("LPDDR4") ||
            normalized.contains("LP4") ||
            normalized.contains("DDR4") && normalized.contains("LP") -> "LPDDR4"

            // LPDDR3
            normalized.contains("LPDDR3") ||
            normalized.contains("LP3") ||
            normalized.contains("DDR3") && normalized.contains("LP") -> "LPDDR3"

            // LPDDR2
            normalized.contains("LPDDR2") ||
            normalized.contains("LP2") -> "LPDDR2"

            // DDR5 (非LP)
            normalized.contains("DDR5") -> "DDR5"

            // DDR4 (非LP)
            normalized.contains("DDR4") -> "DDR4"

            // DDR3 (非LP)
            normalized.contains("DDR3") -> "DDR3"

            else -> "Unknown"
        }
    }

    /**
     * 根据 Android SDK 版本和发布年份估算内存类型
     */
    private fun estimateMemoryType(): String {
        return try {
            val sdkInt = android.os.Build.VERSION.SDK_INT
            val year = android.os.Build.TIME / 1000 / 60 / 60 / 24 / 365 + 1970

            // 根据 SDK 版本和年份推测
            when {
                // Android 14+ (2023年后)，旗舰设备可能使用 LPDDR5X
                sdkInt >= 34 && year >= 2023 -> "LPDDR5X (estimated)"

                // Android 13 (2022-2023)，高端设备使用 LPDDR5
                sdkInt >= 33 && year >= 2022 -> "LPDDR5 (estimated)"

                // Android 12 (2021-2022)，开始出现 LPDDR5
                sdkInt >= 31 && year >= 2021 -> "LPDDR5 (estimated)"

                // Android 11 (2020-2021)，主流使用 LPDDR4X
                sdkInt >= 30 && year >= 2020 -> "LPDDR4X (estimated)"

                // Android 10 (2019-2020)，使用 LPDDR4X
                sdkInt >= 29 && year >= 2019 -> "LPDDR4X (estimated)"

                // 更早期的设备，使用 LPDDR4 或 LPDDR3
                sdkInt >= 28 -> "LPDDR4 (estimated)"

                else -> "LPDDR3 (estimated)"
            }
        } catch (e: Exception) {
            "Unknown"
        }
    }

    /**
     * 获取内存通道数
     * 通道数影响内存带宽，常见的有单通道、双通道、四通道
     *
     * @return 内存通道数 (1/2/4)，默认返回 2（双通道）
     */
    private fun getMemoryChannels(): Int {
        return try {
            // 尝试从设备树或内核日志获取
            val dmesgChannels = Runtime.getRuntime()
                .exec("dmesg | grep -i 'memory.*channel'")
                .inputStream.bufferedReader().readText()

            // 解析通道数,默认返回 2
            when {
                dmesgChannels.contains("dual", ignoreCase = true) -> 2
                dmesgChannels.contains("quad", ignoreCase = true) -> 4
                dmesgChannels.contains("single", ignoreCase = true) -> 1
                else -> 2 // 默认双通道
            }
        } catch (e: Exception) {
            2
        }
    }

    /**
     * 获取 ZRAM（压缩内存）信息
     * ZRAM 是一种压缩内存技术，可以在内存不足时提供额外的"虚拟内存"
     *
     * @return Pair<总大小, 已使用大小> (字节)
     */
    private fun getZramInfo(): Pair<Long, Long> {
        return try {
            var total = 0L
            var used = 0L

            // 检查所有 zram 设备 (通常是 zram0 到 zram7)
            for (i in 0..7) {
                val devicePath = "/sys/block/zram$i"
                if (!File(devicePath).exists()) continue

                // 读取总大小
                File("$devicePath/disksize").readText().trim().toLongOrNull()?.let {
                    total += it
                }

                // 读取已使用大小
                File("$devicePath/mem_used_total").readText().trim().toLongOrNull()?.let {
                    used += it
                }
            }

            Pair(total, used)
        } catch (e: Exception) {
            Pair(0L, 0L)
        }
    }

    /**
     * 格式化字节数为人类可读的格式
     *
     * @param bytes 字节数
     * @return 格式化后的字符串 (如 "4.00 GB", "512.00 MB")
     */
    fun formatBytes(bytes: Long): String {
        return when {
            bytes < 1024 -> "$bytes B"
            bytes < 1024 * 1024 -> String.format(java.util.Locale.US, "%.2f KB", bytes / 1024.0)
            bytes < 1024 * 1024 * 1024 -> String.format(java.util.Locale.US, "%.2f MB", bytes / (1024.0 * 1024))
            else -> String.format(java.util.Locale.US, "%.2f GB", bytes / (1024.0 * 1024 * 1024))
        }
    }
}