#include "filedialoghelper.h"

#include <QFileDialog>
#include <QStandardPaths>
#include <QDir>
#include <QFileSystemWatcher>
#include <QFileInfo>
#include <QFileInfoList>
#include <QUrl>
#include <QVariant>
#include <QPixmap>
#include <QImage>
#include <QPainter>
#include <QMessageBox>
#include <QDateTime>
#include <QApplication>

#include "kaglobal.h"

#include "cmainwnd.h"

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

// 静态工具：为 QFileDialog 添加 U 盘等挂载点到侧边栏，并监听变化
void FileDialogHelper::setupRemovableSidebar(QFileDialog &dialog)
{
    QList<QUrl> baseSidebar = dialog.sidebarUrls();
    int sidebarNum = 8; // 最大添加 U 盘数，可以自己定义
    QString home = QDir::homePath().section("/", -1, -1);
    QString mnt = QStringLiteral("/media/") + home + QStringLiteral("/");

    QDir mntDir(mnt);
    mntDir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
    QFileInfoList filist = mntDir.entryInfoList();
    QList<QUrl> removableUrls;
    for (int i = 0; i < sidebarNum && i < filist.size(); ++i) {
        QFileInfo fi = filist.at(i);
        // 华为990、9a0需要屏蔽最小系统挂载的目录
        if (fi.fileName() == QLatin1String("2691-6AB8"))
            continue;
        removableUrls << QUrl(QStringLiteral("file://") + fi.filePath());
    }

    auto *fsw = new QFileSystemWatcher(&dialog);
    fsw->addPath(mnt);

    QObject::connect(fsw, &QFileSystemWatcher::directoryChanged, &dialog,
                     [sidebarNum, &baseSidebar, &dialog](const QString &path) {
        QDir dir(path);
        dir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
        QFileInfoList list = dir.entryInfoList();
        QList<QUrl> urls;
        for (int i = 0; i < sidebarNum && i < list.size(); ++i) {
            QFileInfo fi = list.at(i);
            if (fi.fileName() == QLatin1String("2691-6AB8"))
                continue;
            urls << QUrl(QStringLiteral("file://") + fi.filePath());
        }
        dialog.setSidebarUrls(baseSidebar + urls);
        dialog.update();
    });

    QObject::connect(&dialog, &QFileDialog::finished, &dialog, [&dialog, baseSidebar]() {
        dialog.setSidebarUrls(baseSidebar);
    });

    dialog.setSidebarUrls(baseSidebar + removableUrls);
}

QString FileDialogHelper::openSupportedFile(int typeNum, QWidget *parent)
{
    FileType type = FileType(typeNum);

    QFileDialog dialog(parent);
    dialog.setModal(true);
    dialog.setWindowModality(Qt::WindowModal);  // 确保窗口模态
    dialog.setWindowTitle(QObject::tr("Open File"));
    dialog.setDirectory(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation));
    dialog.setViewMode(QFileDialog::Detail);
    dialog.setFileMode(QFileDialog::ExistingFile);
    dialog.setOption(QFileDialog::HideNameFilterDetails);

    setupRemovableSidebar(dialog);

    QString format;
    const QStringList supportDoc = g_supportDocFormats;
    const QStringList supportPic = g_supportPicFormats;

    if (type == IMAGE) {
        // 图片
        format = "(";
        for (const QString &str : supportPic)
            format += "*." + str + " ";
        format += ");;";

        const QString supportFormatsClassify =
                "(*.bmp);;"
                "(*.jpe *.jpeg *.jpg);;"
                "(*.pbm);;"
                "(*.pgm);;"
                "(*.png);;"
                "(*.ppm);;"
                "(*.tiff);;"
                "(*.webp)";
        format += supportFormatsClassify;
    } else if (type == DOCUMENT) {
        // 文档
        format = "(";
        for (const QString &str : supportDoc)
            format += "*." + str + " ";
        format += ");;";

        const QString supportFormatsClassify =
                "(*.txt);;"
                "(*.doc *.docx);;"
                "(*.pdf);;"
                "(*.wps);;"
                "(*.pptx *.ppt);;"
                "(*.ofd)";
        format += supportFormatsClassify;
    } else {
        // 0 或其它值：全部支持类型
        format = "(";
        QString imageFormat = "(";
        QString docFormat = "(";

        for (const QString &str : supportDoc) {
            docFormat += "*." + str + " ";
            format += "*." + str + " ";
        }
        docFormat += ");;";

        for (const QString &str : supportPic) {
            imageFormat += "*." + str + " ";
            format += "*." + str + " ";
        }
        imageFormat += ");;";
        format += ");;";

        const QString supportFormatsClassify =
                "(*.txt);;"
                "(*.doc *.docx);;"
                "(*.pdf);;"
                "(*.wps);;"
                "(*.pptx *.ppt);;"
                "(*.ofd);;"
                "(*.bmp);;"
                "(*.jpe *.jpeg *.jpg);;"
                "(*.pbm);;"
                "(*.pgm);;"
                "(*.png);;"
                "(*.ppm);;"
                "(*.tiff);;"
                "(*.webp)";

        format = format + imageFormat + docFormat + supportFormatsClassify;
    }

    dialog.setNameFilter(format);

    // 使用 exec() 而不是静态方法，确保正确的父子窗口关系
    if (dialog.exec() == QDialog::Accepted) {
        QStringList files = dialog.selectedFiles();
        if (!files.isEmpty()) {
            return files.first();
        }
    }

    return QString();
}

QString FileDialogHelper::openWritingFile(int flag, QWidget *parent)
{
    if (flag == 0) {
        // 上传本地文件
        QFileDialog dialog(parent);
        dialog.setModal(true);
        dialog.setWindowModality(Qt::WindowModal);
        dialog.setWindowTitle(QObject::tr("Open File"));
        dialog.setDirectory(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation));
        dialog.setViewMode(QFileDialog::Detail);
        dialog.setFileMode(QFileDialog::ExistingFile);
        dialog.setOption(QFileDialog::HideNameFilterDetails);

        setupRemovableSidebar(dialog);

        QString format;
        QStringList supportFile = { "doc", "docx", "pdf" };
        for (const QString &str : supportFile)
            format += "*." + str + " ";
        dialog.setNameFilter(format);

        if (dialog.exec() == QDialog::Accepted) {
            QStringList files = dialog.selectedFiles();
            if (!files.isEmpty()) {
                return files.first();
            }
        }
        return QString();
    }
}

QString FileDialogHelper::openWritingFile(int flag)
{
    return FileDialogHelper::openWritingFile(flag, nullptr);
}

bool FileDialogHelper::saveImage(const QString &base64Image)
{
    // 获取 main.qml 的 QQuickWindow 作为父窗口（Wayland 环境下需要）
    QQuickWindow *quickWindow = nullptr;
    for (int i = 0; i < qApp->topLevelWindows().count(); i++) {
        QWindow *w = qApp->topLevelWindows().at(i);
        if (w->objectName() == "mainWindow") {
            quickWindow = qobject_cast<QQuickWindow *>(w);
            break;
        }
    }
    
    return FileDialogHelper::saveImage(base64Image, quickWindow);
}

bool FileDialogHelper::saveImage(const QString &base64Image, QQuickWindow *quickWindow)
{
    bool ok = false;
    QPixmap pixmap;

    // 去掉前缀
    QStringList parts = base64Image.split(",");
    if(parts.length() == 2)
    {
        QString imageData = parts.at(1);
        QByteArray byteArray = QByteArray::fromBase64(imageData.toLocal8Bit());
        pixmap.loadFromData(byteArray);
    }
    if(pixmap.isNull())
    {
        KyInfo() << "pixmap is null";
        return false;
    }

    // 获取当前时间
    QDateTime currentTime = QDateTime::currentDateTime();
    QString formattedTime = currentTime.toString("yyyyMMdd_hhmmss");
    // 使用格式化后的时间作为文件名
    QString fileName = "aiassistant_" + formattedTime + ".png";
    // 使用 Globals::getDefaultSavePath() 获取默认保存路径，与QML设置界面保持一致
    QString baseDir = Globals::getinstance()->getDefaultSavePath();

    QString path;
    if(baseDir.endsWith("/"))
    {
        path = baseDir + fileName;
    }
    else
    {
        path = baseDir + "/" + fileName;
    }

    //wayland环境下，构造函数必须加parent， setModal(true)
    QFileDialog *fileDialog = new QFileDialog;
    fileDialog->setAccessibleName("kylin-aiassistant_QFileDialog_fileDialog");
    fileDialog->winId();
    if (quickWindow) {
        fileDialog->windowHandle()->setTransientParent(qobject_cast<QWindow *>(quickWindow));
    }
    fileDialog->setModal(true);
    fileDialog->setNameFilter(QLatin1String("PNG(*.png);;JPE(*.jpe);;JPEG(*.jpeg);;JPG(*.jpg);;PBM(*.pbm);;PGM(*.pgm);;BMP(*.bmp);;PPM(*.ppm);;TIFF(*.tiff);;WEBP(*.webp)"));
    fileDialog->setDirectory(baseDir);
    fileDialog->setAcceptMode(QFileDialog::AcceptSave);
    fileDialog->selectFile(path);

    if(fileDialog->exec() == QFileDialog::Accepted)
    {
        QString savePath = fileDialog->selectedFiles().at(0);

        QFileInfo fileName = savePath;
        if(savePath.isNull())
        {
            delete fileDialog;
            return false;
        }

        if(fileName.suffix().isNull())
        {
            savePath += QLatin1String(".png");
        }
        fileName = savePath;
        QString name = fileName.fileName();
        QString msg;
        QString message;
        if(!name.startsWith(QChar('.'), Qt::CaseInsensitive))
        {
            QFileInfo fileInfo(savePath);
            QStringList parts = base64Image.split(",");
            // 解码 Base64 字符串
            QByteArray decodedData;
            if(parts.length() == 2)
            {
                QString imageData = parts.at(1);
                decodedData = QByteArray::fromBase64(imageData.toLatin1());
            }
            if(fileInfo.suffix() == "jpeg"|| fileInfo.suffix() == "pgm"|| fileInfo.suffix() == "pbm" || fileInfo.suffix() == "ppm" || fileInfo.suffix() == "jpg"){
                // jpeg pgm pbm ppm jpg保存白色背景会填充黑色，额外处理，其中pgm pbm只支持黑白像素
                QImage originalImage;
                originalImage.loadFromData(decodedData);
                // 创建带有白色背景的新图像
                QImage newImage(originalImage.size(), QImage::Format_RGB32);
                newImage.fill(Qt::white);
                // 使用QPainter在新图像上绘制原图
                QPainter painter(&newImage);
                painter.drawImage(0, 0, originalImage);
                painter.end();
                // 保存图像
                if (newImage.save(savePath)) {
                    ok = true;
                } else {
                    ok = false;
                }
            }else if(fileInfo.suffix() == "jpe"){
                // 使用 QImage 加载解码后的数据
                // jpe保存会报错，额外处理
                QImage img;
                if (img.loadFromData(decodedData)) {
                    // 保存为 .jpe 格式（实际上是 JPEG 格式）
                    if (img.save(savePath, "JPEG")) {
                        ok = true;
                    } else {
                        ok = false;
                    }
                } else {
                    qDebug() << "Failed to load image from decoded data.";
                }
            }else if(fileInfo.suffix() == "bmp"){
                // bmp保存白色背景会填充黑色，额外处理
                QImage image;
                image = image.convertToFormat(QImage::Format_RGB32);
                if (image.loadFromData(decodedData)) {
                    if (image.save(savePath)) {
                        ok = true;
                    } else {
                        ok = false;
                    }
                } else {
                    qDebug() << "Failed to load image from decoded data.";
                }
            }else{
                ok = pixmap.save(savePath);
            }
        }
        if(ok)
        {
            QString pathNoFile = savePath.left(savePath.lastIndexOf(QLatin1String("/")));
            message = QObject::tr("Image saved as ") + savePath;
            msg = "<a href=\"" + savePath + "\">" + message + "</a>";
        }
        else
        {
            if(name.contains(QChar('/')))
            {
                msg = QObject::tr("file name can not contains '/'");
            }
            else if(name.startsWith(QChar('.'), Qt::CaseInsensitive))
            {
                msg = QObject::tr("can not save file as hide file");
            }
            else if(name.length() > 255)
            {
                msg = QObject::tr("can not save  because filename too long");
            }
            else
            {
                msg = QObject::tr("Error trying to save as ") + savePath;
            }
            QMessageBox saveErrBox(QMessageBox::Warning, QObject::tr("Save Error"), msg);
            saveErrBox.exec();
        }
    }
    
    delete fileDialog;
    return ok;
}


