#include "licensemanager.h"
#include <QProcess>
#include <QFile>
#include <QTextStream>
#include <QMessageBox>
#include <QCryptographicHash>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QDir>
#include <QApplication>
#include <QClipboard>
#include <QDebug>
#include <QTcpSocket>
#include <QJsonDocument>
#include <QJsonObject>
#include <QDateTime>

// ==================== 静态成员初始化 ====================
// 加密密钥
const QByteArray LicenseManager::encryptKey = "GetonAgain2026SecretKey!@#$%";
// 客户专用密码 - 根据不同客户修改此值
const QString LicenseManager::customerPassword = "nuobo123";

// ==================== LicenseManager 实现 ====================

LicenseManager::LicenseManager(QObject *parent) : QObject(parent)
{
}

QString LicenseManager::getMachineUUID()
{
    QString uuid;

#ifdef Q_OS_WIN
    // Windows: 通过WMI获取主板UUID
    QProcess process;
    process.start("wmic", QStringList() << "csproduct" << "get" << "UUID");
    process.waitForFinished(5000);
    QString output = QString::fromLocal8Bit(process.readAllStandardOutput());

    // 解析输出，获取UUID
    QStringList lines = output.split('\n', Qt::SkipEmptyParts);
    for (const QString &line : lines)
    {
        QString trimmed = line.trimmed();
        if (!trimmed.isEmpty() && trimmed != "UUID" && trimmed.contains('-'))
        {
            uuid = trimmed;
            break;
        }
    }
#else
    // Linux/Mac: 读取machine-id
    QFile file("/etc/machine-id");
    if (file.open(QIODevice::ReadOnly))
    {
        uuid = QString::fromUtf8(file.readAll()).trimmed();
        file.close();
    }
#endif

    if (uuid.isEmpty())
    {
        // 备用方案：使用机器名+用户名的哈希
        QString fallback = QSysInfo::machineHostName() + QDir::homePath();
        uuid = QString::fromLatin1(QCryptographicHash::hash(fallback.toUtf8(), QCryptographicHash::Md5).toHex());
    }

    return uuid;
}

QString LicenseManager::getLicenseFilePath()
{
    // 激活文件放在程序目录下
    return QCoreApplication::applicationDirPath() + "/license.gal";
}

QString LicenseManager::encrypt(const QString &plainText)
{
    QByteArray data = plainText.toUtf8();

    // 第一步：计算明文的SHA256哈希（用于完整性校验）
    QByteArray hash = QCryptographicHash::hash(data, QCryptographicHash::Sha256);

    // 第二步：构造加密数据 = 哈希前8字节 + 原始数据
    QByteArray toEncrypt;
    toEncrypt.append(hash.left(8)); // 8字节校验头
    toEncrypt.append(data);

    // 第三步：多层XOR加密
    QByteArray encrypted;
    for (int i = 0; i < toEncrypt.size(); ++i)
    {
        unsigned char c = static_cast<unsigned char>(toEncrypt[i]);

        // 第一层：与主密钥XOR
        c = c ^ static_cast<unsigned char>(encryptKey[i % encryptKey.size()]);

        // 第二层：字节置换（非线性变换）
        c = static_cast<unsigned char>((c * 7 + 13) % 256);

        // 第三层：与位置相关的混淆
        c = c ^ static_cast<unsigned char>((i * 31 + 17) % 256);

        encrypted.append(static_cast<char>(c));
    }

    // 第四步：Base64编码
    return QString::fromLatin1(encrypted.toBase64());
}

QString LicenseManager::decrypt(const QString &encryptedText)
{
    // Base64解码
    QByteArray encrypted = QByteArray::fromBase64(encryptedText.toLatin1());

    if (encrypted.size() < 9) // 至少8字节校验头 + 1字节数据
    {
        return QString();
    }

    // 逆向解密
    QByteArray decrypted;
    for (int i = 0; i < encrypted.size(); ++i)
    {
        unsigned char c = static_cast<unsigned char>(encrypted[i]);

        // 逆向第三层：位置混淆
        c = c ^ static_cast<unsigned char>((i * 31 + 17) % 256);

        // 逆向第二层：字节置换的逆运算
        // 原式: c' = (c * 7 + 13) % 256
        // 需要找到 7 在 mod 256 下的逆元
        // 7 * 183 = 1281 = 5 * 256 + 1, 所以 7^(-1) ≡ 183 (mod 256)
        c = static_cast<unsigned char>(((c + 256 - 13) * 183) % 256);

        // 逆向第一层：与主密钥XOR
        c = c ^ static_cast<unsigned char>(encryptKey[i % encryptKey.size()]);

        decrypted.append(static_cast<char>(c));
    }

    // 提取校验头和原始数据
    QByteArray storedHash = decrypted.left(8);
    QByteArray originalData = decrypted.mid(8);

    // 验证哈希
    QByteArray computedHash = QCryptographicHash::hash(originalData, QCryptographicHash::Sha256);
    if (computedHash.left(8) != storedHash)
    {
        qDebug() << "License integrity check failed - data may be corrupted or tampered";
        return QString(); // 返回空表示解密失败
    }

    return QString::fromUtf8(originalData);
}

QString LicenseManager::generateActivationCode(const QString &uuid)
{
    // 生成激活码格式: encrypt(UUID:password)
    // 这个方法供管理员/供应商使用，为特定设备生成激活码
    QString plainText = uuid + ":" + customerPassword;
    return encrypt(plainText);
}

bool LicenseManager::readAndVerifyLicense()
{
    QString filePath = getLicenseFilePath();
    QFile file(filePath);

    if (!file.exists())
    {
        qDebug() << "License file not found:" << filePath;
        return false;
    }

    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        qDebug() << "Cannot open license file";
        return false;
    }

    QTextStream in(&file);
    QString encryptedContent = in.readAll().trimmed();
    file.close();

    if (encryptedContent.isEmpty())
    {
        qDebug() << "License file is empty";
        return false;
    }

    // 解密
    QString decrypted = decrypt(encryptedContent);
    qDebug() << "Decrypted license content (debug)";

    // 解析格式: UUID:password
    // 使用 lastIndexOf 因为UUID中也可能包含冒号（虽然通常不会）
    int separatorIndex = decrypted.lastIndexOf(':');
    if (separatorIndex == -1)
    {
        qDebug() << "Invalid license format: no separator";
        return false;
    }

    QString licenseUUID = decrypted.left(separatorIndex);
    QString password = decrypted.mid(separatorIndex + 1);

    // 获取本机真实UUID
    QString currentUUID = getMachineUUID();

    qDebug() << "License UUID:" << licenseUUID;
    qDebug() << "Current UUID:" << currentUUID;

    // 验证UUID是否匹配
    if (licenseUUID != currentUUID)
    {
        qDebug() << "UUID mismatch - license not valid for this machine";
        return false;
    }

    // 验证密码是否正确
    if (password != customerPassword)
    {
        qDebug() << "Password mismatch";
        return false;
    }

    qDebug() << "License verification successful";
    return true;
}

bool LicenseManager::saveLicenseFile(const QString &activationCode)
{
    QString filePath = getLicenseFilePath();
    QFile file(filePath);

    if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
    {
        qDebug() << "Cannot save license file to:" << filePath;
        return false;
    }

    QTextStream out(&file);
    out << activationCode;
    file.close();

    qDebug() << "License file saved to:" << filePath;
    return true;
}

bool LicenseManager::showActivationDialog(QWidget *parent)
{
    ActivationDialog dialog(parent);

    while (true)
    {
        if (dialog.exec() != QDialog::Accepted)
        {
            return false; // 用户取消
        }

        QString serverAddress = dialog.getServerAddress();
        QString activationCode = dialog.getActivationCode();

        // 解析服务器地址和端口
        QString host;
        int port = 8080;
        if (serverAddress.contains(':'))
        {
            QStringList parts = serverAddress.split(':');
            host = parts[0];
            port = parts[1].toInt();
        }
        else
        {
            host = serverAddress;
        }

        // 显示连接中提示
        QMessageBox waitMsg(parent);
        waitMsg.setWindowTitle("请稍候");
        waitMsg.setText("正在连接激活服务器...");
        waitMsg.setStandardButtons(QMessageBox::NoButton);
        waitMsg.show();
        QApplication::processEvents();

        // 连接服务器
        QTcpSocket socket;
        socket.connectToHost(host, port);

        bool connected = socket.waitForConnected(10000); // 10秒超时

        if (!connected)
        {
            waitMsg.close();
            QMessageBox::warning(parent, "连接失败",
                                 QString("无法连接到服务器 %1:%2\n请检查网络连接和服务器地址。").arg(host).arg(port));
            continue;
        }

        // 构建激活请求
        QJsonObject requestObj;
        requestObj["uuid"] = getMachineUUID();
        requestObj["code"] = activationCode;
        requestObj["timestamp"] = QDateTime::currentDateTime().toString(Qt::ISODate);
        QJsonDocument doc(requestObj);
        QByteArray requestData = doc.toJson(QJsonDocument::Compact);

        // 发送请求
        socket.write(requestData);
        socket.write("\n");
        socket.flush();

        // 等待响应
        if (!socket.waitForReadyRead(15000)) // 15秒超时
        {
            waitMsg.close();
            socket.close();
            QMessageBox::warning(parent, "激活失败", "服务器响应超时，请重试。");
            continue;
        }

        QByteArray response = socket.readAll();
        socket.close();
        waitMsg.close();

        // 解析响应
        QJsonDocument responseDoc = QJsonDocument::fromJson(response);
        if (responseDoc.isNull() || !responseDoc.isObject())
        {
            QMessageBox::warning(parent, "激活失败", "服务器响应格式错误。");
            continue;
        }

        QJsonObject responseObj = responseDoc.object();
        QString status = responseObj["status"].toString();

        if (status == "success")
        {
            QString license = responseObj["license"].toString();

            // 保存激活文件
            if (saveLicenseFile(license))
            {
                // 验证保存的激活文件
                if (readAndVerifyLicense())
                {
                    QMessageBox::information(parent, "成功", "软件激活成功！");
                    return true;
                }
            }

            QMessageBox::warning(parent, "错误", "保存激活文件失败！");
        }
        else
        {
            QString message = responseObj["message"].toString();
            if (message.isEmpty())
                message = "激活失败，请检查激活码是否正确。";

            QMessageBox::StandardButton retry = QMessageBox::warning(
                parent, "激活失败", message,
                QMessageBox::Retry | QMessageBox::Cancel);

            if (retry != QMessageBox::Retry)
            {
                return false;
            }
        }
    }
}

// ==================== ActivationDialog 实现 ====================

ActivationDialog::ActivationDialog(QWidget *parent) : QDialog(parent)
{
    setWindowTitle("软件激活");
    setFixedSize(420, 240);
    setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);

    // 确保对话框接收键盘输入
    setAttribute(Qt::WA_InputMethodEnabled, true);

    setupUI();
}

QString ActivationDialog::getServerAddress() const
{
    return serverEdit->text().trimmed();
}

QString ActivationDialog::getActivationCode() const
{
    return codeEdit->text().trimmed();
}

void ActivationDialog::setupUI()
{
    QVBoxLayout *mainLayout = new QVBoxLayout(this);
    mainLayout->setContentsMargins(25, 20, 25, 20);
    mainLayout->setSpacing(12);

    // 标题
    QLabel *titleLabel = new QLabel("软件激活");
    titleLabel->setStyleSheet("font-size: 20px; font-weight: bold; color: #333;");
    titleLabel->setAlignment(Qt::AlignCenter);
    mainLayout->addWidget(titleLabel);

    mainLayout->addSpacing(8);

    // 提示信息
    QLabel *infoLabel = new QLabel("请输入激活服务器地址和激活码");
    infoLabel->setStyleSheet("font-size: 12px; color: #666;");
    infoLabel->setAlignment(Qt::AlignCenter);
    mainLayout->addWidget(infoLabel);

    mainLayout->addSpacing(8);

    // 服务器地址输入 - 使用 QFormLayout 风格
    QHBoxLayout *serverLayout = new QHBoxLayout();
    serverLayout->setSpacing(10);
    QLabel *serverLabel = new QLabel("服务器地址:");
    serverLabel->setFixedWidth(80);
    serverLabel->setStyleSheet("font-size: 13px;");

    serverEdit = new QLineEdit();
    serverEdit->setMinimumHeight(32);
    serverEdit->setPlaceholderText("例如: 192.168.1.100:8080");
    serverEdit->setStyleSheet("font-size: 13px; padding: 4px 8px;");

    serverLayout->addWidget(serverLabel);
    serverLayout->addWidget(serverEdit, 1);
    mainLayout->addLayout(serverLayout);

    // 激活码输入
    QHBoxLayout *codeLayout = new QHBoxLayout();
    codeLayout->setSpacing(10);
    QLabel *codeLabel = new QLabel("激  活  码:");
    codeLabel->setFixedWidth(80);
    codeLabel->setStyleSheet("font-size: 13px;");

    codeEdit = new QLineEdit();
    codeEdit->setMinimumHeight(32);
    codeEdit->setPlaceholderText("例如: RB2026-XXXX-XXXX-XXXX");
    codeEdit->setStyleSheet("font-size: 13px; padding: 4px 8px;");

    codeLayout->addWidget(codeLabel);
    codeLayout->addWidget(codeEdit, 1);
    mainLayout->addLayout(codeLayout);

    mainLayout->addSpacing(15);

    // 按钮
    QHBoxLayout *btnLayout = new QHBoxLayout();
    btnLayout->addStretch();

    confirmBtn = new QPushButton("激  活");
    confirmBtn->setFixedSize(100, 36);
    confirmBtn->setStyleSheet(
        "QPushButton { background-color: #4CAF50; color: white; font-size: 14px; font-weight: bold; border-radius: 4px; }"
        "QPushButton:hover { background-color: #45a049; }"
        "QPushButton:pressed { background-color: #3d8b40; }");
    connect(confirmBtn, &QPushButton::clicked, this, &ActivationDialog::onConfirmClicked);

    cancelBtn = new QPushButton("退  出");
    cancelBtn->setFixedSize(100, 36);
    cancelBtn->setStyleSheet(
        "QPushButton { background-color: #f44336; color: white; font-size: 14px; font-weight: bold; border-radius: 4px; }"
        "QPushButton:hover { background-color: #da3c30; }"
        "QPushButton:pressed { background-color: #c62828; }");
    connect(cancelBtn, &QPushButton::clicked, this, &QDialog::reject);

    btnLayout->addWidget(confirmBtn);
    btnLayout->addSpacing(20);
    btnLayout->addWidget(cancelBtn);
    btnLayout->addStretch();
    mainLayout->addLayout(btnLayout);

    // 确保可以Tab切换
    setTabOrder(serverEdit, codeEdit);
    setTabOrder(codeEdit, confirmBtn);
    setTabOrder(confirmBtn, cancelBtn);
}

void ActivationDialog::onConfirmClicked()
{
    if (serverEdit->text().trimmed().isEmpty())
    {
        QMessageBox::warning(this, "提示", "请输入服务器地址！");
        serverEdit->setFocus();
        return;
    }

    if (codeEdit->text().trimmed().isEmpty())
    {
        QMessageBox::warning(this, "提示", "请输入激活码！");
        codeEdit->setFocus();
        return;
    }

    accept();
}
