#include <cpucontroller.h>
#include <QProcess>
#include <QDebug>
#include <QMessageBox>
#include <fstream>
#include <unistd.h>
#include <sstream>

std::string CPUController::getCpuModelName()
{
    std::ifstream cpuinfo_file("/proc/cpuinfo");
    if (cpuinfo_file.is_open())
    {
        std::string line;
        while (std::getline(cpuinfo_file, line))
        {
            if (line.find("model name") != std::string::npos)
            {
                cpuinfo_file.close();
                return line.substr(line.find(":") + 2);
            }
        }
        cpuinfo_file.close();
    }
    return "Unknown CPU model";
}

void CPUController::enableCpuSMT()
{
    QStringList args;
    args << "sh" << "-c" << "echo on | tee /sys/devices/system/cpu/smt/control";

    int exitCode = QProcess::execute("pkexec", args);
    if (exitCode == 0)
    {
        qDebug() << "SMT enabled successfully";
    }
    else
    {
        qWarning() << "Error:" << exitCode;
    }
}

void CPUController::disableCpuSMT()
{
    QStringList args;
    args << "sh" << "-c" << "echo off | tee /sys/devices/system/cpu/smt/control";

    int exitCode = QProcess::execute("pkexec", args);
    if (exitCode == 0)
    {
        qDebug() << "SMT disabled successfully";
    }
    else
    {
        qWarning() << "Error:" << exitCode;
        std::string errorString = "无法关闭超线程，错误码：" + std::to_string(exitCode);
    }
}

bool CPUController::getCpuSMTStatus()
{
    std::ifstream smt_file("/sys/devices/system/cpu/smt/control");
    if (smt_file.is_open())
    {
        std::string smt_control;
        std::getline(smt_file, smt_control);
        smt_file.close();
        return (smt_control == "on");
    }
    return false;
}

int CPUController::getCpuCoreOnlineCount()
{
    return sysconf(_SC_NPROCESSORS_ONLN);
}

int CPUController::getCpuCoreCount()
{
    return sysconf(_SC_NPROCESSORS_CONF);
}

void CPUController::enableCpuBoost()
{
    QStringList args;
    args << "sh" << "-c" << "echo 1 | tee /sys/devices/system/cpu/cpufreq/boost";
    int exitCode = QProcess::execute("pkexec", args);
    if (exitCode == 0)
    {
        qDebug() << "CPU Boost enabled successfully";
    }
    else
    {
        qWarning() << "Error:" << exitCode;
        // QMessageBox::critical(this, "错误", "无法启用CPU Boost！");
    }
}

void CPUController::disableCpuBoost()
{
    QStringList args;
    args << "sh" << "-c" << "echo 0 | tee /sys/devices/system/cpu/cpufreq/boost";
    int exitCode = QProcess::execute("pkexec", args);
    if (exitCode == 0)
    {
        qDebug() << "CPU Boost disabled successfully";
    }
    else
    {
        qWarning() << "Error:" << exitCode;
        // QMessageBox::critical(this, "错误", "无法关闭CPU睿频！");
    }
}
bool CPUController::getCpuBoostStatus()
{
    std::ifstream boost_file("/sys/devices/system/cpu/cpufreq/boost");
    if (boost_file.is_open())
    {
        std::string boost_control;
        std::getline(boost_file, boost_control);
        boost_file.close();
        return (boost_control == "1");
    }
    return false;
}

bool CPUController::setAllCpuMaxFrequency(int frequency)
{
    QStringList args;
    // 避免多次授权
    args << "sh" << "-c" << QString("for policy in /sys/devices/system/cpu/cpufreq/policy*; do "
                                    "  cpu_index=$(basename \"$policy\" | sed 's/policy//'); "
                                    "  online_file=\"/sys/devices/system/cpu/cpu$cpu_index/online\"; "
                                    "  if [ -f \"$online_file\" ] && [ \"$(cat \"$online_file\")\" = \"0\" ]; then "
                                    "    continue; "
                                    "  fi; "
                                    "  echo %1 | sudo tee \"$policy/scaling_max_freq\" > /dev/null; "
                                    "done")
                                .arg(frequency);

    int exitCode = QProcess::execute("pkexec", args);
    if (exitCode == 0)
    {
        qDebug() << "CPU Max Frequency set successfully";
        return true;
    }
    else
    {
        qWarning() << "Error setting max frequency:" << exitCode;
        return false;
    }
}

bool CPUController::setAllCpuMinFrequency(int frequency)
{
    QStringList args;
    args << "sh" << "-c" << QString("for policy in /sys/devices/system/cpu/cpufreq/policy*; do "
                                    "  cpu_index=$(basename \"$policy\" | sed 's/policy//'); "
                                    "  online_file=\"/sys/devices/system/cpu/cpu$cpu_index/online\"; "
                                    "  if [ -f \"$online_file\" ] && [ \"$(cat \"$online_file\")\" = \"0\" ]; then "
                                    "    continue; "
                                    "  fi; "
                                    "  echo %1 | sudo tee \"$policy/scaling_min_freq\" > /dev/null; "
                                    "done")
                                .arg(frequency);

    int exitCode = QProcess::execute("pkexec", args);
    if (exitCode == 0)
    {
        qDebug() << "CPU Min Frequency set successfully";
        return true;
    }
    else
    {
        qWarning() << "Error setting min frequency:" << exitCode;
        return false;
    }
}

std::vector<int> CPUController::getAvailableFrequencies(int cpu)
{
    std::vector<int> frequencies;
    std::string frequencies_str;

    std::vector<std::string> possible_paths = {
        QString("/sys/devices/system/cpu/cpu%1/cpufreq/scaling_available_frequencies").arg(cpu).toStdString(),
        QString("/sys/devices/system/cpu/cpu%1/cpufreq/scaling_frequencies").arg(cpu).toStdString(),
        "/sys/devices/system/cpu/cpufreq/scaling_available_frequencies",
        "/sys/devices/system/cpu/cpufreq/scaling_frequencies"
    };

    std::vector<std::string> range_paths = {
        QString("/sys/devices/system/cpu/cpu%1/cpufreq/cpuinfo_min_freq").arg(cpu).toStdString(),
        QString("/sys/devices/system/cpu/cpu%1/cpufreq/cpuinfo_max_freq").arg(cpu).toStdString(),
        QString("/sys/devices/system/cpu/cpu%1/cpufreq/scaling_min_freq").arg(cpu).toStdString(),
        QString("/sys/devices/system/cpu/cpu%1/cpufreq/scaling_max_freq").arg(cpu).toStdString()
    };
    
    // 首先尝试获取离散频率列表
    for (const auto& path : possible_paths) {
        std::ifstream freq_file(path);
        if (freq_file.is_open()) {
            std::getline(freq_file, frequencies_str);
            freq_file.close();
            
            if (!frequencies_str.empty()) {
                std::istringstream iss(frequencies_str);
                std::string freq_str;
                while (std::getline(iss, freq_str, ' ')) {
                    try {
                        frequencies.push_back(std::stoi(freq_str));
                    } catch (const std::exception& e) {
                        qWarning() << "Error parsing frequency value:" << freq_str.c_str() << e.what();
                    }
                }
                
                if (!frequencies.empty()) {
                    qDebug() << "Found frequencies from:" << path.c_str();
                    return frequencies;
                }
            }
        }
    }
    
    // 如果离散频率列表不存在，尝试从频率范围生成
    int min_freq = 0, max_freq = 0;
    
    // 获取最小频率
    std::ifstream min_file(range_paths[0]); // cpuinfo_min_freq
    if (min_file.is_open()) {
        std::string min_str;
        std::getline(min_file, min_str);
        if (!min_str.empty()) {
            try {
                min_freq = std::stoi(min_str);
            } catch (const std::exception& e) {
                qWarning() << "Error parsing min frequency:" << min_str.c_str() << e.what();
            }
        }
        min_file.close();
    }
    
    // 获取最大频率
    std::ifstream max_file(range_paths[1]); // cpuinfo_max_freq
    if (max_file.is_open()) {
        std::string max_str;
        std::getline(max_file, max_str);
        if (!max_str.empty()) {
            try {
                max_freq = std::stoi(max_str);
            } catch (const std::exception& e) {
                qWarning() << "Error parsing max frequency:" << max_str.c_str() << e.what();
            }
        }
        max_file.close();
    }

    if (min_freq > 0 && max_freq > min_freq) {
        qDebug() << "Generating frequencies from range:" << min_freq << "-" << max_freq;
        
        frequencies.push_back(min_freq);
        
        // 中间频率点（25%，50%，75%）
        int range = max_freq - min_freq;
        frequencies.push_back(min_freq + range / 4);
        frequencies.push_back(min_freq + range / 2);
        frequencies.push_back(min_freq + 3 * range / 4);
        frequencies.push_back(max_freq);
        std::sort(frequencies.begin(), frequencies.end());
        frequencies.erase(std::unique(frequencies.begin(), frequencies.end()), frequencies.end());
        
        return frequencies;
    }
    
    
    qWarning() << "Could not determine available frequencies for CPU" << cpu;
    return frequencies;
}

void CPUController::setAllCpuGovernor(std::string governor)
{
    QStringList args;
    args << "sh" << "-c" << QString("for policy in /sys/devices/system/cpu/cpufreq/policy*; do "
                                    "  cpu_index=$(basename \"$policy\" | sed 's/policy//'); "
                                    "  online_file=\"/sys/devices/system/cpu/cpu$cpu_index/online\"; "
                                    "  if [ -f \"$online_file\" ] && [ \"$(cat \"$online_file\")\" = \"0\" ]; then "
                                    "    continue; "
                                    "  fi; "
                                    "  echo %1 | sudo tee \"$policy/scaling_governor\" > /dev/null; "
                                    "done")
                                .arg(governor.c_str());

    int exitCode = QProcess::execute("pkexec", args);
    if (exitCode == 0)
    {
        qDebug() << "CPU Governor set successfully";
    }
    else
    {
        qWarning() << "Error setting governor:" << exitCode;
    }
}

std::vector<std::string> CPUController::getAvailableGovernors(int cpu)
{
    return std::vector<std::string>();
}

std::map<int, int> CPUController::getLogicalToClusterMap()
{
    std::ifstream cpuinfo("/proc/cpuinfo");
    std::map<int, int> logicalToCluster;

    if (!cpuinfo.is_open())
    {
        qDebug() << "Failed to open /proc/cpuinfo";
        return logicalToCluster;
    }

    std::string line;
    int processorId = -1;
    int coreId = -1;
    int socketId = -1;
    int clusterId = -1;
    bool hasCluster = false;

    while (std::getline(cpuinfo, line))
    {
        std::istringstream iss(line);
        std::string key, val;

        if (line.find("processor") != std::string::npos && line.find(":") != std::string::npos)
        {
            sscanf(line.c_str(), "processor\t: %d", &processorId);
        }
        else if (line.find("core id") != std::string::npos && line.find(":") != std::string::npos)
        {
            sscanf(line.c_str(), "core id\t: %d", &coreId);
        }
        else if (line.find("physical id") != std::string::npos && line.find(":") != std::string::npos)
        {
            sscanf(line.c_str(), "physical id\t: %d", &socketId);
        }
        else if (line.find("cluster") != std::string::npos && line.find(":") != std::string::npos)
        {
            sscanf(line.c_str(), "cluster\t: %d", &clusterId);
            hasCluster = true;
        }

        // 空行或文件结尾，保存当前解析的数据
        if (line.empty() || cpuinfo.peek() == EOF)
        {
            if (processorId >= 0)
            {
                if (hasCluster)
                {
                    logicalToCluster[processorId] = clusterId;
                }
                else
                {
                    // 使用 socket_id * 1024 + core_id 模拟丛集分组
                    logicalToCluster[processorId] = (socketId << 16) | coreId;
                }
            }
            // 重置变量
            processorId = -1;
            coreId = -1;
            socketId = -1;
            clusterId = -1;
        }
    }

    cpuinfo.close();
    return logicalToCluster;
}