#include "HttpClient.h"



HttpClient::HttpClient(QObject *parent)
    : QObject(parent)
{
    m_networkAccessManager = new QNetworkAccessManager(this);
    m_timer = new QTimer(this);
    m_timer->setInterval(8000);
    m_timer->setSingleShot(true);
    connect(m_timer, SIGNAL(timeout()), &m_eventLoop, SLOT(quit()));
}

HttpClient::~HttpClient()
{
    delete m_networkAccessManager;
    delete m_timer;
}


bool HttpClient::get(QNetworkRequest &request)
{
    QUrl url = request.url();
    
    // 转换 URL 为 QString
    QString urlString = url.toString();
    
    // 检查 URL 字符串是否包含特定的子字符串
    
    QNetworkReply *reply;
    bool success = false;
    request.setPriority(QNetworkRequest::HighPriority);
    for(int i = 0 ; i < m_networkErrorRetry + 1; i++)//
    {
        reply = m_networkAccessManager->get(request);
        processReply(reply);
        
        if (m_error == QNetworkReply::NoError)
        {
            
            success = true;
            break;
        }
    }
    return success;
}

bool HttpClient::post(QNetworkRequest &request, const QByteArray &data)
{
    QNetworkReply *reply;
    bool success = false;
    request.setPriority(QNetworkRequest::HighPriority);
    for (int i = 0; i < m_networkErrorRetry + 1; i++)
    {
        reply = m_networkAccessManager->post(request, data);
        processReply(reply);
        if (m_error == QNetworkReply::NoError)
        {
            success = true;
            break;
        }
    }
    return success;
}
bool HttpClient::downloadFile(QNetworkRequest request, const QString &filePath,
                              QString &fullPathName,QString &extension)
{
    bool success = false;
    QDir dir(filePath);
    if (!dir.exists()) {
        dir.mkpath(".");
    }
    Common & instace= Common::getInstance();
    QString filePa = QDir::toNativeSeparators(filePath +extension);
    
    QSslConfiguration config= QSslConfiguration::defaultConfiguration();
    config.setProtocol(QSsl::AnyProtocol);
    config.setPeerVerifyMode(QSslSocket::VerifyNone);
    request.setSslConfiguration(config);
    
    QNetworkReply* reply = m_networkAccessManager->get(request);
    reply->ignoreSslErrors();
    
    QEventLoop loop;
    QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
    
    QFile file(filePa);
    if (!file.open(QIODevice::WriteOnly)) {
        qInfo() << "Failed to open file for writing";
        reply->deleteLater(); // 确保释放网络回复资源
        return false;
    }
    
    QObject::connect(reply, &QNetworkReply::readyRead, [&]() {
        file.write(reply->readAll());
    });
    
    QObject::connect(reply, &QNetworkReply::finished, [&, reply]() {
        if (reply->error() != QNetworkReply::NoError) {
            qInfo() << "Download failed:" << reply->errorString();
            file.remove(); // 删除不完整的文件
        } else {
            success = true;
            file.flush();
            file.close();
        }
        reply->deleteLater();
    });
    
    loop.exec();
    fullPathName = filePa;
    
    return success;
}

bool HttpClient::uploadFile(QNetworkRequest request,const QString& accessKeyId,
                            const QString& accessKeySecret,
                            const QString &filePath,QString & bucketName,QString &securityToken){
    bool success = false;
    
    QFile *file = new QFile(filePath, this);
    qInfo() << "filePath"<<filePath;
    
    if (!file->open(QIODevice::ReadOnly)) {
        qInfo() << "uploadFile Failed to open file for reading";
        return false;
    }
    QByteArray fileData = file->readAll();
    if(fileData.isEmpty()){
        qInfo() << "uploadFile = file.readAll()";
        return false;
    }
    
    QFileInfo fileInfo(file->fileName());
    QString fileName = fileInfo.fileName(); // 获取文件名，包括扩展名
    
    QSslConfiguration config = QSslConfiguration::defaultConfiguration();
    config.setProtocol(QSsl::AnyProtocol);
    config.setPeerVerifyMode(QSslSocket::VerifyNone);
    request.setSslConfiguration(config);
    
    Common & instace= Common::getInstance();
    
    // 获取当前的UTC时间
    QDateTime now = QDateTime::currentDateTimeUtc();
    
    // 设置英文环境，确保月份和星期格式正确
    QLocale englishLocale(QLocale::English, QLocale::UnitedStates);
    
    // 使用英文环境格式化日期时间为GMT字符串
    QString gmtDateString = englishLocale.toString(now, "ddd, dd MMM yyyy HH:mm:ss 'GMT'");
    
    QString oSSHeaders="x-oss-security-token:";
    oSSHeaders.append(securityToken);
    QString signature= instace.generateSignature(accessKeySecret,"PUT","","video/mp4",gmtDateString,oSSHeaders,"/"+bucketName+"/"+fileName);
    request.setRawHeader("Date", gmtDateString.toUtf8());
    
    QString authHeaderValue = "OSS " + accessKeyId + ":" + signature;
    request.setRawHeader("Authorization", authHeaderValue.toUtf8());
    request.setRawHeader("X-Oss-Security-Token",securityToken.toUtf8());
    request.setHeader(QNetworkRequest::ContentTypeHeader, "video/mp4");
    request.setHeader(QNetworkRequest::ContentLengthHeader, QString::number(fileData.size()).toUtf8());
    QNetworkReply *reply = m_networkAccessManager->put(request,fileData);
    reply->ignoreSslErrors();
    
    QEventLoop loop;
    connect(reply, &QNetworkReply::finished, this, [reply, file,&loop, &success]() {
        if (reply->error() == QNetworkReply::NoError) {
            qInfo() << "Upload successful!";
            file->remove();
            success=true;
        } else {
            qInfo() << "Upload failed:" << reply->errorString();
        }
        file->close();
        file->deleteLater();
        reply->deleteLater();
        loop.quit();
    });
    // 启动事件循环，等待请求完成
    loop.exec();
    
    
    return success;
}
void HttpClient::processReply(QNetworkReply *reply)
{
    connect(reply, SIGNAL(finished()), &m_eventLoop, SLOT(quit()));
    
    m_text.clear();
    m_timer->start();
    m_eventLoop.exec();
    
    if (m_timer->isActive())
    {
        m_timer->stop();
        
        m_error = reply->error();
        m_errorString = reply->errorString();
        if (reply->bytesAvailable() > 0)
        {
            m_data = reply->readAll();
            QTextCodec *codec = QTextCodec::codecForHtml(m_data, QTextCodec::codecForName("utf-8"));
            if (codec)
                m_text = codec->toUnicode(m_data);
        }
        else
        {
            m_data.clear();
            m_text.clear();
        }
    }
    else
    {
        reply->abort();
        m_error = QNetworkReply::TimeoutError;
    }
    
    delete reply;
}
QString HttpClient::errorString() const{
    return m_errorString;
}

QString HttpClient::errorCode() const
{
    switch (m_error)
    {
    case QNetworkReply::NoError: return "NoError";
    case QNetworkReply::ConnectionRefusedError: return "ConnectionRefusedError";
    case QNetworkReply::RemoteHostClosedError: return "RemoteHostClosedError";
    case QNetworkReply::HostNotFoundError: return "HostNotFoundError";
    case QNetworkReply::TimeoutError: return "TimeoutError";
    case QNetworkReply::OperationCanceledError: return "OperationCanceledError";
    case QNetworkReply::SslHandshakeFailedError: return "SslHandshakeFailedError";
    case QNetworkReply::TemporaryNetworkFailureError: return "TemporaryNetworkFailureError";
    case QNetworkReply::ProxyConnectionRefusedError: return "ProxyConnectionRefusedError";
    case QNetworkReply::ProxyConnectionClosedError: return "ProxyConnectionClosedError";
    case QNetworkReply::ProxyNotFoundError: return "ProxyNotFoundError";
    case QNetworkReply::ProxyTimeoutError: return "ProxyTimeoutError";
    case QNetworkReply::ProxyAuthenticationRequiredError: return "ProxyAuthenticationRequiredError";
    case QNetworkReply::ContentAccessDenied: return "ContentAccessDenied";
    case QNetworkReply::ContentOperationNotPermittedError: return "ContentOperationNotPermittedError";
    case QNetworkReply::ContentNotFoundError: return "ContentNotFoundError";
    case QNetworkReply::AuthenticationRequiredError: return "AuthenticationRequiredError";
    case QNetworkReply::ContentReSendError: return "ContentReSendError";
    case QNetworkReply::ProtocolUnknownError: return "ProtocolUnknownError";
    case QNetworkReply::ProtocolInvalidOperationError: return "ProtocolInvalidOperationError";
    case QNetworkReply::UnknownNetworkError: return "UnknownNetworkError";
    case QNetworkReply::UnknownProxyError: return "UnknownProxyError";
    case QNetworkReply::UnknownContentError: return "UnknownContentError";
    case QNetworkReply::ProtocolFailure: return "ProtocolFailure";
    }
    return "UnknownError";
}

QString HttpClient::text() const
{
    return m_text;
}
