// imagedownloader.cpp
#include "imagedownloader.h"
#include <QStandardPaths>
#include <QDebug>
#include <QJsonArray>
#include <QUrl>
#include <QTimer>

ImageDownloader::ImageDownloader(QObject *parent)
    : QObject(parent)
    , m_networkManager(new QNetworkAccessManager(this))
    , m_currentReply(nullptr)
    , m_currentFile(nullptr)
    , m_isDownloading(false)
    , m_totalImages(0)
    , m_downloadedImages(0)
    , m_failedDownloads(0)
    , m_currentFileProgress(0)
    , m_currentFileSize(0)
    , m_cancelRequested(false)
{
    // Set default download directory to user's Pictures folder
    QString defaultDir = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
    if (defaultDir.isEmpty())
    {
        defaultDir = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
    }
    setDownloadDirectory(defaultDir + "/StellarMateImages");
}

ImageDownloader::~ImageDownloader()
{
    cancelDownload();
}

void ImageDownloader::startDownload(const QString &downloadDir, const QVariantList &selectedImages)
{
    if (m_isDownloading)
    {
        qWarning() << "Download already in progress";
        return;
    }

    if (selectedImages.isEmpty())
    {
        emit downloadCompleted(false, 0, 0, "No images selected");
        return;
    }

    // Set download directory
    setDownloadDirectory(downloadDir);

    // Create directory if it doesn't exist
    QDir dir(m_downloadDirectory);
    if (!dir.exists())
    {
        if (!dir.mkpath("."))
        {
            emit downloadCompleted(false, 0, 0, "Failed to create download directory: " + m_downloadDirectory);
            return;
        }
    }

    // Clear previous queue
    m_downloadQueue.clear();
    m_downloadedImages = 0;
    m_failedDownloads = 0;
    m_cancelRequested = false;

    // Parse selected images and build download queue
    for (const QVariant &imageVar : selectedImages)
    {
        QVariantMap imageMap = imageVar.toMap();
        QVariantMap metadata = imageMap.value("metadata").toMap();

        ImageDownloadInfo info;
        info.uuid = metadata.value("uuid").toString();
        info.filename = metadata.value("filename").toString();
        info.rawUrl = imageMap.value("raw").toString();

        // Construct local path
        info.localPath = m_downloadDirectory + "/" + info.filename;

        // Check if file already exists, add a number suffix if needed
        int counter = 1;
        QString basePath = info.localPath;
        QString baseFilename = info.filename;
        int dotIndex = baseFilename.lastIndexOf('.');
        QString nameWithoutExt = (dotIndex > 0) ? baseFilename.left(dotIndex) : baseFilename;
        QString extension = (dotIndex > 0) ? baseFilename.mid(dotIndex) : "";

        while (QFile::exists(info.localPath))
        {
            info.localPath = m_downloadDirectory + "/" + nameWithoutExt + "_" + QString::number(counter) + extension;
            counter++;
        }

        if (!info.uuid.isEmpty() && !info.filename.isEmpty() && !info.rawUrl.isEmpty())
        {
            m_downloadQueue.enqueue(info);
        }
    }

    setTotalImages(m_downloadQueue.size());

    if (m_downloadQueue.isEmpty())
    {
        emit downloadCompleted(false, 0, 0, "No valid images to download");
        return;
    }

    qDebug() << "Starting download of" << m_totalImages << "images to" << m_downloadDirectory;

    setIsDownloading(true);
    downloadNextImage();
}

void ImageDownloader::cancelDownload()
{
    if (!m_isDownloading)
    {
        return;
    }

    qDebug() << "Cancelling download...";
    m_cancelRequested = true;

    if (m_currentReply)
    {
        m_currentReply->abort();
    }

    if (m_currentFile)
    {
        m_currentFile->close();
        m_currentFile->deleteLater();
        m_currentFile = nullptr;
    }

    m_downloadQueue.clear();
    setIsDownloading(false);

    emit downloadCompleted(false, m_downloadedImages, m_failedDownloads,
                           "Download cancelled by user");
}

void ImageDownloader::downloadNextImage()
{
    if (m_cancelRequested)
    {
        return;
    }

    if (m_downloadQueue.isEmpty())
    {
        // All downloads complete
        setIsDownloading(false);

        QString message;
        bool success = (m_failedDownloads == 0);

        if (success)
        {
            message = QString("Successfully downloaded %1 image(s) to:\n%2")
                      .arg(m_downloadedImages)
                      .arg(m_downloadDirectory);
        }
        else
        {
            message = QString("Downloaded %1 image(s), %2 failed.\nSaved to:\n%3")
                      .arg(m_downloadedImages)
                      .arg(m_failedDownloads)
                      .arg(m_downloadDirectory);
        }

        emit downloadCompleted(success, m_downloadedImages, m_failedDownloads, message);
        return;
    }

    // Get next image
    ImageDownloadInfo info = m_downloadQueue.dequeue();

    setCurrentFileName(info.filename);
    setCurrentFileProgress(0);
    setCurrentFileSize(0);

    qDebug() << "Downloading:" << info.filename << "from" << info.rawUrl;

    // Create file
    m_currentFile = new QFile(info.localPath);
    if (!m_currentFile->open(QIODevice::WriteOnly))
    {
        qWarning() << "Failed to create file:" << info.localPath;
        emit fileDownloadFailed(info.filename, "Failed to create local file");

        m_failedDownloads++;
        delete m_currentFile;
        m_currentFile = nullptr;

        // Continue with next image
        QTimer::singleShot(100, this, &ImageDownloader::downloadNextImage);
        return;
    }

    // Start download
    QNetworkRequest request(QUrl(info.rawUrl));
    request.setRawHeader("User-Agent", "StellarMate-ImageDownloader/1.0");

    m_currentReply = m_networkManager->get(request);

    connect(m_currentReply, &QNetworkReply::finished,
            this, &ImageDownloader::onDownloadFinished);
    connect(m_currentReply, &QNetworkReply::downloadProgress,
            this, &ImageDownloader::onDownloadProgress);
    connect(m_currentReply, &QNetworkReply::readyRead,
            this, &ImageDownloader::onDownloadReadyRead);

    emit downloadProgress(m_downloadedImages + 1, m_totalImages, info.filename);
}

void ImageDownloader::onDownloadFinished()
{
    if (!m_currentReply)
    {
        return;
    }

    QString filename = m_currentFileName;
    bool success = false;

    if (m_currentReply->error() == QNetworkReply::NoError)
    {
        // Write any remaining data
        if (m_currentFile && m_currentReply->bytesAvailable() > 0)
        {
            m_currentFile->write(m_currentReply->readAll());
        }

        success = true;
        m_downloadedImages++;
        setDownloadedImages(m_downloadedImages);

        qDebug() << "Successfully downloaded:" << filename;
    }
    else
    {
        qWarning() << "Download failed for" << filename << ":" << m_currentReply->errorString();
        emit fileDownloadFailed(filename, m_currentReply->errorString());
        m_failedDownloads++;

        // Delete partial file
        if (m_currentFile)
        {
            QString path = m_currentFile->fileName();
            m_currentFile->close();
            QFile::remove(path);
        }
    }

    // Cleanup
    if (m_currentFile)
    {
        m_currentFile->close();
        m_currentFile->deleteLater();
        m_currentFile = nullptr;
    }

    m_currentReply->deleteLater();
    m_currentReply = nullptr;

    // Continue with next image after a short delay
    QTimer::singleShot(100, this, &ImageDownloader::downloadNextImage);
}

void ImageDownloader::onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal)
{
    setCurrentFileProgress(bytesReceived);
    setCurrentFileSize(bytesTotal);
}

void ImageDownloader::onDownloadReadyRead()
{
    if (m_currentFile && m_currentReply)
    {
        m_currentFile->write(m_currentReply->readAll());
    }
}

void ImageDownloader::setIsDownloading(bool downloading)
{
    if (m_isDownloading != downloading)
    {
        m_isDownloading = downloading;
        emit isDownloadingChanged();
    }
}

void ImageDownloader::setTotalImages(int total)
{
    if (m_totalImages != total)
    {
        m_totalImages = total;
        emit totalImagesChanged();
    }
}

void ImageDownloader::setDownloadedImages(int downloaded)
{
    if (m_downloadedImages != downloaded)
    {
        m_downloadedImages = downloaded;
        emit downloadedImagesChanged();
    }
}

void ImageDownloader::setCurrentFileName(const QString &filename)
{
    if (m_currentFileName != filename)
    {
        m_currentFileName = filename;
        emit currentFileNameChanged();
    }
}

void ImageDownloader::setCurrentFileProgress(qint64 progress)
{
    if (m_currentFileProgress != progress)
    {
        m_currentFileProgress = progress;
        emit currentFileProgressChanged();
    }
}

void ImageDownloader::setCurrentFileSize(qint64 size)
{
    if (m_currentFileSize != size)
    {
        m_currentFileSize = size;
        emit currentFileSizeChanged();
    }
}

void ImageDownloader::setDownloadDirectory(const QString &dir)
{
    if (m_downloadDirectory != dir)
    {
        m_downloadDirectory = dir;
        emit downloadDirectoryChanged();
    }
}