/**
 * "UltimateDailyWallpaper" Copyright (C) 2026 Patrice Coni
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

#include <QUrl>
#include <QFile>
#include <QDir>
#include <QFileInfo>
#include <QApplication>
#include <QDebug>
#include <QThread>
#include <QProcess>
#include <QDateTime>
#include <QImage>
#include <QSqlQuery>
#include <QSqlError>
#include <QSettings>
#include <QDomElement>
#include <QDomDocument>

#include "bing_wallpaper_downloader.h"

Bing_wallpaper_downloader::Bing_wallpaper_downloader()
{
    _picture_height = 0;
    _picture_width  = 0;
}

bool Bing_wallpaper_downloader::SetExtendedFunctionInterface()
{
    return false;
}

bool Bing_wallpaper_downloader::SetAdditionalFunctionInterface()
{
    return false;
}

bool Bing_wallpaper_downloader::SetMenuInterface()
{
    return false;
}

bool Bing_wallpaper_downloader::SetSubMenuInterface()
{
    return false;
}

void Bing_wallpaper_downloader::get_picture(bool downloadthumb,
                                            QString _picturedir,
                                            QString lang,
                                            int year,
                                            int month,
                                            int day)
{    
    Q_UNUSED(downloadthumb);
    Q_UNUSED(year);
    Q_UNUSED(month);
    Q_UNUSED(day);

    _picture_height = 0;
    _picture_width  = 0;

    parse(lang);

    if (_urlBase.isEmpty() ||
        _description.isEmpty() ||
        _titletext.isEmpty() ||
        _page_url.isEmpty())
    {
        qWarning() << "plugin: metadata incomplete – aborting.";
        return;
    }

    if (check_exists() == 255)
    {
        qDebug() << "The most recent image is already stored.";
        return;
    }

    if (download_picture("https://www.bing.com" + _urlBase + "_UHD.jpg",
                         _picturedir, false) != 0)
    {
        qWarning() << "plugin: wallpaper download failed.";
        return;
    }

    QImage img(_picturedir + "/" + filename);
    if (img.isNull())
    {
        qWarning() << "plugin: downloaded image is invalid.";
        return;
    }

    _picture_height = img.height();
    _picture_width  = img.width();

    if (_picture_height <= 0 || _picture_width <= 0)
    {
        qWarning() << "plugin: invalid image dimensions.";
        return;
    }

    if (download_picture("https://www.bing.com" + _urlBase + "_400x240.jpg",
                         QDir::homePath()+"/.UltimateDailyWallpaper/thumbnails",
                         true) != 0)
    {
        qWarning() << "Plugin: thumbnail download failed.";
        return;
    }

    emit download_successful(
        _description,
        _copyright,
        provider(),
        _titletext,
        filename,
        _page_url,
        thumbfilename,
        _picture_height,
        _picture_width,
        0,
        false,
        ""
    );
}

QString Bing_wallpaper_downloader::pluginname()
{
    return tr("Daily Bing wallpaper Downloader");
}

QString Bing_wallpaper_downloader::plugininfo()
{
    QString info;
    info.append("Name: "+pluginname());
    info.append("\n");
    info.append("Description: Bing wallpaper of the day\n");
    info.append("License: GPL-3.0+\n");
    info.append("Author: Patrice Coni\n");
    info.append("Version: ");
    info.append("v");
    info.append(PLUGIN_VERSION);

    return info;
}

QString Bing_wallpaper_downloader::provider()
{
    return tr("Bing");
}

Bing_wallpaper_downloader::~Bing_wallpaper_downloader()
{
}

void Bing_wallpaper_downloader::parse(QString _lang)
{
    QString baseURL="https://www.bing.com/HPImageArchive.aspx?format=xml&idx=0&n=1&mkt=";
    QString _language;

    if(_lang.contains("de"))
    {
        _language="de-DE";
    }
    else if(_lang.contains("fr"))
    {
        _language="fr-FR";
    }
    else if(_lang.contains("it"))
    {
        _language="it-IT";
    }
    else if(_lang.contains("es"))
    {
        _language="es-ES";
    }
    else
    {
        _language="en-US";
    }

    if(request_download_json(baseURL+_language)==true)
    {
        QDomDocument basefile;

        basefile.setContent(_reply);

        QDomElement element= basefile.documentElement().firstChild().firstChild().toElement();

        while(!element.isNull()) {
              if(element.tagName()=="urlBase")
              {
                  _urlBase = element.firstChild().toText().data();
              }
              if(element.tagName()=="copyright")
              {
                  _description = element.firstChild().toText().data();
              }
              if(element.tagName()=="copyrightlink")
              {
                  _page_url = element.firstChild().toText().data();
              }
              if(element.tagName()=="headline")
              {
                  _titletext = element.firstChild().toText().data();
              }
              element = element.nextSibling().toElement();
        }
    }

    filename.clear();
    filename.append(_urlBase);
#if QT_VERSION >= 0x060000
    filename.remove(QRegularExpression(QString::fromUtf8("[-`~!@#$%^&*()_â€”+=|:;<>Â«Â»,.?/{}\'\"\\\\\\[\\\\\\]\\\\]")));
#else
    filename.remove(QRegExp(QString::fromUtf8("[-`~!@#$%^&*()_+=|:;<>«»,.?/{}'\"\\[\\]\\\\]")));
#endif
    filename.append("_UHD.jpg");

    thumbfilename.clear();
    thumbfilename.append("thumb"+_urlBase);
#if QT_VERSION >= 0x060000
    thumbfilename.remove(QRegularExpression(QString::fromUtf8("[-`~!@#$%^&*()_â€”+=|:;<>Â«Â»,.?/{}\'\"\\\\\\[\\\\\\]\\\\]")));
#else
    thumbfilename.remove(QRegExp(QString::fromUtf8("[-`~!@#$%^&*()_+=|:;<>«»,.?/{}'\"\\[\\]\\\\]")));
#endif
    thumbfilename.append(".jpg");
}

bool Bing_wallpaper_downloader::request_download_json(QString _targeturl)
{
    QEventLoop loop;
    QObject::connect(&dl_manager,&QNetworkAccessManager::finished,&loop,&QEventLoop::quit);
    QUrl targeturl=_targeturl;
    reply = dl_manager.get(QNetworkRequest(targeturl));
    loop.exec();
    if (reply->bytesAvailable())
    {
        if (reply->error() == QNetworkReply::NoError)
        {
            _reply = reply->readAll();
            delete reply;
            reply=0;
        }
        else
        {
            qDebug() << reply->errorString();
            return false;
        }
    }

    loop.quit();
    loop.exit();

    return true;
}

int Bing_wallpaper_downloader::download_picture(QString _dlurl, QString dlpath, bool _is_thumb)
{
    QDir _picturedir(dlpath);
    if(!_picturedir.exists())
    {
        _picturedir.mkpath(dlpath);
    }

    QStringList arguments;

    if(_is_thumb==true)
    {
        arguments << _dlurl << "--output" << dlpath+"/"+thumbfilename;
    } else
    {
        arguments << _dlurl << "--output" << dlpath+"/"+filename;
    }

    QProcess proc;

    if(!arguments.isEmpty())
    {
        proc.start("curl", arguments);
        proc.waitForFinished();
        proc.close();
    }
    else
    {
        qDebug()<<"No arguments.";
    }

    return proc.exitCode();
}

int Bing_wallpaper_downloader::check_exists()
{
    QString content;
    QString _databaseFilePath = QDir::homePath() + "/.UltimateDailyWallpaper/udw_database.sqlite";

    // Create a unique connection name based on the current thread ID
    QString connName = QString("check_exists_conn_%1").arg((quintptr)QThread::currentThreadId());

    // Wrap the QSqlDatabase in its own scope to ensure destruction before removeDatabase()
    {
        QSqlDatabase udw_db = QSqlDatabase::addDatabase("QSQLITE", connName);
        udw_db.setDatabaseName(_databaseFilePath);

        // Attempt to open the database
        if (!udw_db.open()) {
            qWarning() << "Database could not be opened!";
            QSqlDatabase::removeDatabase(connName); // Clean up connection if opening fails
            return 100;
        }

        // Scope for QSqlQuery ensures it is destroyed before we close and remove the connection
        {
            QSqlQuery uwp_query(udw_db);

            // Prepare the SQL query with a parameter to avoid SQL injection
            uwp_query.prepare("SELECT filename FROM udw_history WHERE filename = ?");
            uwp_query.addBindValue(filename);

            // Execute the query and handle errors
            if (!uwp_query.exec()) {
                qWarning() << "Query execution failed:" << uwp_query.lastError();
                udw_db.close();
                QSqlDatabase::removeDatabase(connName); // Remove connection safely
                return 100;
            }

            // If a matching record exists, store its filename
            if (uwp_query.next()) {
                content = uwp_query.value(0).toString();
            }

            // Finish the query explicitly (optional, safe)
            uwp_query.finish();
        } // QSqlQuery destroyed here

        // Close the database connection
        udw_db.close();
    } // QSqlDatabase destroyed here

    // Remove the named connection after all objects using it are destroyed
    QSqlDatabase::removeDatabase(connName);

    // Determine return code based on whether the file exists
    if (!content.isEmpty() && filename == content) {
        return 255; // Exact match found
    } else if (!content.isEmpty()) {
        return 2;   // Record exists but filename doesn't exactly match
    } else {
        return 1;   // No record found
    }
}



