#include "tchttpservice.h"
QScopedPointer<TCHttpService> TCHttpService::m_instance;

TCHttpService *TCHttpService::getInstance()
{
    if (m_instance.isNull()) {
        m_instance.reset(new TCHttpService);
    }

    return m_instance.data();
}

void TCHttpService::apiLogin()
{
    QByteArray pwdMd5 = QCryptographicHash::hash(m_firstPwd.toUtf8(), QCryptographicHash::Md5);
    QString md5Hex = pwdMd5.toHex();

    QString urlStr;
   if (m_enableSsl)
        urlStr = "https://" + m_domain + "/api/login";
   else
       urlStr = "http://" + m_domain + "/api/login";

    QUrl url(urlStr);
    QJsonObject jsonObj;
    jsonObj["user"]=m_userName;
    jsonObj["pwd"]=md5Hex;
    QJsonDocument jsonDoc(jsonObj);
    QByteArray jsonData = jsonDoc.toJson();
    QMap<QString, QString> headers;
    headers.insert("Content-Type", "application/json");

    QNetworkReply* reply = nullptr;

   QNetworkRequest request(url);
    for (auto ite = headers.constBegin(); ite != headers.constEnd(); ite++){
       request.setRawHeader(ite.key().toUtf8(), ite.value().toUtf8());
    }
   reply = m_manager.post(request, jsonData);

       QObject::connect(reply, &QNetworkReply::finished, [this, reply]() {

       emit requestFinished(reply, "login");
   });
}

void TCHttpService::apiMyfileCount()
{

    QString urlStr;
    if (m_enableSsl)
        urlStr = "https://" + m_domain + "/api/myfiles";
    else
        urlStr = "http://" + m_domain + "/api/myfiles";

    QMap<QString, QString> headers;
    headers.insert("Content-Type", "application/json");

    QMap<QString, QString> params;
    params.insert("cmd", "count");
    QUrl url = encodeUrl(urlStr, params);
    QJsonObject jsonObj;
    jsonObj["token"] = m_token;
    jsonObj["user"] = m_userName;
    QJsonDocument jsonDoc(jsonObj);
    QByteArray jsonData = jsonDoc.toJson();

    QNetworkRequest request(url);
    for (auto ite = headers.constBegin(); ite != headers.constEnd(); ite++){
        request.setRawHeader(ite.key().toUtf8(), ite.value().toUtf8());
    }

    QNetworkReply* reply = nullptr;
    reply = m_manager.post(request, jsonData);
    QObject::connect(reply, &QNetworkReply::finished, [this, reply](){

        emit requestFinished(reply, "myfilecount");
    });
}

void TCHttpService::apiMyfileNormal(int start, int count)
{
    QString urlStr;
    if (m_enableSsl)
        urlStr = "https://" + m_domain + "/api/myfiles";
    else
        urlStr = "http://" + m_domain + "/api/myfiles";

    QMap<QString, QString> headers;
    headers.insert("Content-Type", "application/json");

    QMap<QString, QString> params;
    params.insert("cmd", "normal");

    QUrl url = encodeUrl(urlStr, params);
    QNetworkRequest request(url);
    for (auto ite = headers.constBegin(); ite != headers.constEnd(); ite++){
        request.setRawHeader(ite.key().toUtf8(), ite.value().toUtf8());
    }

    QJsonObject jsonObj;
    jsonObj["token"] = m_token;
    jsonObj["user"] = m_userName;
    jsonObj["count"] = count;
    jsonObj["start"] = start;

    QJsonDocument jsonDoc(jsonObj);
    QByteArray jsonData = jsonDoc.toJson();

    QNetworkReply* reply = nullptr;
    reply = m_manager.post(request, jsonData);
    connect(reply, &QNetworkReply::finished, [this, reply](){
        emit requestFinished(reply, "myfilenormal");
    });
}

void TCHttpService::apiMd5(const QString& filePath)
{
    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly)) {
        return;
    }

    QByteArray fileMd5;
    QCryptographicHash hash(QCryptographicHash::Md5);
    if (hash.addData(&file)) {
         fileMd5 = hash.result().toHex();
    }
    else
        return;

    QString urlStr;
    if (m_enableSsl)
        urlStr = "https://" + m_domain + "/api/md5";
    else
        urlStr = "http://" + m_domain + "/api/md5";
    QMap<QString, QString> headers;
    headers.insert("Content-Type", "application/json");
    QString md5Str = QString::fromUtf8(fileMd5);
    QJsonObject jsonObj;
    jsonObj["token"] = m_token;
    jsonObj["md5"] = md5Str;
    jsonObj["filename"] = QFileInfo(file).fileName();
    jsonObj["user"] = m_userName;
    file.close();

    QJsonDocument jsonDoc(jsonObj);
    QByteArray jsonData = jsonDoc.toJson();
    QNetworkReply* reply = nullptr;

    QNetworkRequest request(urlStr);
    reply = m_manager.post(request, jsonData);

    QObject::connect(reply, &QNetworkReply::finished, [this, reply](){
        emit requestFinished(reply, "md5");
    });
}

void TCHttpService::apiUpload(const QString &filePath)
{

    QString urlStr;
    if (m_enableSsl)
        urlStr = "https://" + m_domain + "/api/upload";
    else
        urlStr = "http://" + m_domain + "/api/upload";



    QFile *file = new QFile(filePath);
    if (!file->open(QIODevice::ReadOnly)) {
        qDebug() << "无法打开文件:" << filePath;
        delete file;
        return;
    }

    // 计算文件 MD5
    QCryptographicHash hash(QCryptographicHash::Md5);
    hash.addData(file);
    QString md5 = hash.result().toHex();

    // 重置文件指针
    file->seek(0);

    // 获取文件大小
    qint64 fileSize = file->size();

    // 创建 multipart 请求
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
    QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
#else
    QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormData);
#endif
    // 添加文件部分
    QHttpPart filePart;
    filePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/octet-stream"));
    filePart.setHeader(QNetworkRequest::ContentDispositionHeader,
                       QVariant("form-data; name=\"file\"; filename=\"" + QFileInfo(filePath).fileName() + "\""));
    filePart.setBodyDevice(file);
    multiPart->append(filePart);

    // 添加用户信息部分
    QHttpPart userPart;
    userPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"user\""));
    userPart.setBody(m_userName.toUtf8());
    multiPart->append(userPart);

    // 添加 MD5 部分
    QHttpPart md5Part;
    md5Part.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"md5\""));
    md5Part.setBody(md5.toUtf8());
    multiPart->append(md5Part);

    // 添加文件大小部分
    QHttpPart sizePart;
    sizePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"size\""));
    sizePart.setBody(QString::number(fileSize).toUtf8());
    multiPart->append(sizePart);

    // 创建网络请求
    QNetworkRequest request(urlStr); // 替换为实际的服务器地址
    request.setHeader(QNetworkRequest::ContentTypeHeader, "multipart/form-data; boundary=" + multiPart->boundary());

    // 发送请求
    // QNetworkAccessManager *manager = new QNetworkAccessManager(this);
    QNetworkReply *reply = m_manager.post(request, multiPart);

    // 连接信号槽
    connect(reply, &QNetworkReply::finished, this, [=]() {
        if (reply->error() == QNetworkReply::NoError) {
            qDebug() << "上传成功:";
            apiMyfileCount();
        } else {
            qDebug() << "上传失败:" << reply->errorString();
        }
        reply->deleteLater();
        multiPart->deleteLater();
    });

    connect(reply, &QNetworkReply::uploadProgress, this, [](qint64 bytesSent, qint64 bytesTotal) {
        if (bytesTotal > 0) {
            int progress = (bytesSent * 100) / bytesTotal;
            qDebug() << "上传进度:" << progress << "%";
        }
    });
}

void TCHttpService::apiSharePicShare(const QString &fileName, const QString &md5)
{

    QString urlStr;
    if (m_enableSsl)
        urlStr = "https://" + m_domain + "/api/sharepic";
    else
        urlStr = "http://" + m_domain + "/api/sharepic";

    QMap<QString, QString> headers;
    QMap<QString, QString> body;
    QMap<QString, QString> params;

    headers.insert("Content-Type", "application/json");

    QString bodyStr = QString("\"%1\":\"%2\",\"%3\":\"%4\",\"%5\":\"%6\",\"%7\":\"%8\"").arg("token").arg(m_token).
            arg("user").arg(m_userName).arg("md5").arg(md5).arg("filename").arg(fileName);

    params.insert("cmd", "share");

}

void TCHttpService::setConfiguration(QString userName, QString firstPwd, QString domain)
{
    this->m_domain = domain;
    this->m_userName = userName;
    this->m_firstPwd = firstPwd;
    connect(this, &TCHttpService::requestFinished, [this](QNetworkReply* reply, QString api){
        QByteArray rawData = reply->readAll();
        if (api == "login") {

            QJsonDocument jsonDoc = QJsonDocument::fromJson(rawData);
            if (jsonDoc.isEmpty())
                return;
            QJsonObject jsonObj = jsonDoc.object();
            int code = jsonObj["code"].toInt();
            if (code == 0) {
                this->m_token = jsonObj["token"].toString();
                qDebug() << this->m_token;

                apiMyfileCount();

            }
        }
        if (api == "myfilecount") {
            QJsonDocument jsonDoc = QJsonDocument::fromJson(rawData);
            if (jsonDoc.isEmpty())
                return;
            QJsonObject jsonObj = jsonDoc.object();
            int code = jsonObj["code"].toInt();

            if (code == 0) {
                int total = jsonObj["total"].toInt();
                this->m_total = total;
                int n = total / 10 + 1;
                int pendingRequests = n;
                for (int i = 0; i < n; i++) {
                    int count = (total - i * 10 >= 10) ? 10 : (total - i * 10);
                    apiMyfileNormal(i*10, count);
                }


            }
        }
        if (api == "myfilenormal") {
            static int loginCnt = 0;

            QJsonDocument jsonDoc = QJsonDocument::fromJson(rawData);
            if (jsonDoc.isEmpty())
                return;
            QJsonObject jsonObj = jsonDoc.object();

            int code = jsonObj["code"].toInt();
            if (code != 0)
                return;
                QJsonArray jsonArray = jsonObj["files"].toArray();
            for (const QJsonValue& value : jsonArray) {
                QJsonObject jsonObj = value.toObject();

                QString file_name = jsonObj["file_name"].toString();
                int share_status = jsonObj["share_status"].toInt();
                QString url = jsonObj["url"].toString();
                qint64 size = jsonObj["size"].toInt();
                QString md5 = jsonObj["md5"].toString();

                QMap<QString, file_info_t>::iterator ite;
                ite = m_fileMap.find(md5);
                if (ite == m_fileMap.end()) {
                    qDebug() << file_name;
                    file_info_t info;
                    info.share_status = share_status;
                    info.size = size;
                    info.url = url;
                    info.file_name = file_name;
                    if (m_isOnline) {
                        qDebug() << "now upload";
                        emit signal_uploadFileSec(url);

                    }
                    m_fileMap.insert(md5, info);
                    // if (m_fileMap.size() == m_total && m_isOnline == false)


                }
#if !DEBUG
                // for(auto ite = m_fileMap.constBegin(); ite != m_fileMap.constEnd(); ite++) {
                //     qDebug() << "fileMap debug:" << ite.value().file_name;
                // }
                qDebug() << "fileMap size:" << m_fileMap.size();
#endif
            }
            if (!m_isOnline) {
                loginCnt++;
                qDebug() << "loginCnt:" << loginCnt;
                if (loginCnt == m_total/10+1) {
                    m_isOnline = true;
                    qDebug() << "login success";
                }
            }

        }
        // if (api == "upload") {
        //     qDebug() <<"upload";
        //     QJsonDocument jsondoc = QJsonDocument::fromJson(rawData);
        //     QJsonObject jsonObj = jsondoc.object();

        //     int code = jsonObj["code"].toInt();

        //     if (code == 0)
        //         this->apiMyfileCount();
        // }
        reply->deleteLater();
    });
    apiLogin();
}

void TCHttpService::setSsl(bool enable)
{
    this->m_enableSsl = enable;
}

bool TCHttpService::getOnlineState()
{
    return m_isOnline;
}

void TCHttpService::setUploadNum(int nb)
{
    this->m_uploadNum = nb;
}

QUrl TCHttpService::encodeUrl(QString urlStr, QMap<QString, QString> params)
{
    QUrlQuery query;
    for(auto ite = params.constBegin(); ite != params.constEnd(); ite++){
        query.addQueryItem(ite.key(), ite.value());
    }

    QUrl url(urlStr);
    url.setQuery(query);

    return url;
}


void TCHttpService::updateFileMap(QJsonObject jsonObj)
{
    // QString fileMD5 = jsonObj["md5"].toString();
    // QString fileUrl = jsonObj["http"].toString();

    // QMap<QString, file_info_t>::iterator ite = m_fileMap.begin();
    // if (ite != m_fileMap.end())
    //     return;

    // m_fileMap.insert(fileMD5, fileUrl);
}

TCHttpService::TCHttpService(QObject *parent) : QObject(parent)
{

}
