#include "eparserdocument.h"
#include "eparserdocument.h"
#include "utils/util.h"

#include <DFileDialog>
#include <DFileIconProvider>

#include <QFuture>
#include <QFutureWatcher>
#include <QtConcurrent>
#include <QLoggingCategory>

#include <docparser.h>

Q_DECLARE_LOGGING_CATEGORY(logAIGUI)

UOSAI_USE_NAMESPACE
DWIDGET_USE_NAMESPACE
DCORE_USE_NAMESPACE

EParserDocument *EParserDocument::instance()
{
    static EParserDocument ins;
    return &ins;
}

void EParserDocument::parserDocument(const QString &docPath)
{    
    QFutureWatcher<QPair<QString, ParserResult>> *futureWatcher = new QFutureWatcher<QPair<QString, ParserResult>>;
    QFuture<QPair<QString, ParserResult>> future = QtConcurrent::run([docPath]{
        std::string stdStrContents = DocParser::convertFile(docPath.toStdString());
        QString contents = Util::textEncodingTransferUTF8(stdStrContents);
        if (contents.isEmpty()) {
            qCWarning(logAIGUI) << "Document parsing failed: No text content found in" << docPath;
            return qMakePair(QString(), ParserResult::NoTextError);
        }

        if (!Util::isValidDocContent(stdStrContents)) {
            qCWarning(logAIGUI) << "Document parsing failed: Invalid content in" << docPath;
            return qMakePair(QString(), ParserResult::ParsingFailed);
        }

        qCDebug(logAIGUI) << "Document parsed successfully:" << docPath;
        return qMakePair(contents, ParserResult::NoError);
    });

    QObject::connect(futureWatcher, &QFutureWatcher<QPair<QString, ParserResult>>::finished, this, [=]{
        QPair<QString, ParserResult> parserRes = futureWatcher->future().result();
        emit sigParserResult(parserRes.second, docPath, parserRes.first);
        futureWatcher->deleteLater();
    });
    futureWatcher->setFuture(future);
}

void EParserDocument::selectDocument(AssistantType type)
{
    DFileDialog fileDlg;
    fileDlg.setDirectory(m_lastImportPath);
    updateSupSuffix(type);
    QString selfilter = tr("Supported files") + (" (%1)");
    selfilter = selfilter.arg(m_supSuffix.join(" "));
    fileDlg.setViewMode(DFileDialog::Detail);
    fileDlg.setFileMode(DFileDialog::ExistingFile);
    fileDlg.setOption(DFileDialog::HideNameFilterDetails);
    fileDlg.setNameFilter(selfilter);
    fileDlg.selectNameFilter(selfilter);
    fileDlg.setObjectName("fileDialogAdd");
    if (DFileDialog::Accepted == fileDlg.exec()) {
        m_lastImportPath = fileDlg.directory().path();
        QStringList selectedPaths = fileDlg.selectedFiles();
        if (selectedPaths.isEmpty()) {
            qCDebug(logAIGUI) << "No file selected in dialog";
            return;
        }

        if (isExceedDocSize(selectedPaths[0])) {
            qCWarning(logAIGUI) << "Selected file exceeds size limit:" << selectedPaths[0];
            emit sigParserStart(QString(), QString(), QString(), ParserStart::ExceedSize);
            return;
        }

        // 文件选择框中创建新文件不会过滤，需要再判断一次后缀
        QFileInfo docInfo(selectedPaths[0]);
        if (!m_supSuffix.contains("*." + docInfo.suffix().toLower())) {
            qCWarning(logAIGUI) << "Unsupported document suffix:" << docInfo.suffix();
            emit sigParserStart(QString(), QString(), QString(), ParserStart::SuffixError);
            return;
        }

        emit sigParserStart(selectedPaths[0], getFileIconData(selectedPaths[0]), QString(), ParserStart::Success);
    }
}

void EParserDocument::updateSupSuffix(AssistantType type)
{
    if (type == AssistantType::UOS_AI || type == AssistantType::AI_TRANSLATION || type == AssistantType::AI_TEXT_PROCESSING || type == AssistantType::AI_WRITING){
        m_supSuffix.clear();
        m_supSuffix << "*.txt"
                    << "*.doc"
                    << "*.docx"
                    << "*.xls"
                    << "*.xlsx"
                    << "*.ppt"
                    << "*.pptx"
                    << "*.pdf";
    } else if (type == AssistantType::PLUGIN_ASSISTANT) {
        m_supSuffix.clear();
        m_supSuffix << "*.docx";
    }
}

void EParserDocument::dragInViewDocument(const QStringList &docPaths, const QString &defaultPrompt, AssistantType type)
{
    if (docPaths.size() > 1) {
        qCWarning(logAIGUI) << "Multiple documents not supported";
        emit sigParserStart(QString(), QString(), QString(), ParserStart::MoreOneError);
        return;
    }

    if (docPaths.size() == 0) {
        qCWarning(logAIGUI) << "No document provided";
        emit sigParserStart(QString(), QString(), QString(), ParserStart::NoDocError);
        return;
    }

    QString docPath = docPaths[0];
    if (isExceedDocSize(docPath)) {
        qCWarning(logAIGUI) << "Document exceeds size limit:" << docPath;
        emit sigParserStart(QString(), QString(), QString(), ParserStart::ExceedSize);
        return;
    }

    QFileInfo docInfo(docPath);
    updateSupSuffix(type);
    if (!m_supSuffix.contains("*." + docInfo.suffix().toLower())) {
        qCWarning(logAIGUI) << "Unsupported document suffix:" << docInfo.suffix();
        emit sigParserStart(QString(), QString(), QString(), ParserStart::SuffixError);
        return;
    }

    emit sigParserStart(docPath, getFileIconData(docPath), defaultPrompt, ParserStart::Success);
}

EParserDocument::EParserDocument()
{
    m_lastImportPath = QStandardPaths::standardLocations(QStandardPaths::HomeLocation).first();

    m_supSuffix << "*.txt"
                << "*.doc"
                << "*.docx"
                << "*.xls"
                << "*.xlsx"
                << "*.ppt"
                << "*.pptx"
                << "*.pdf";
}

bool EParserDocument::isExceedDocSize(const QString &docPath)
{
    bool res = false;

    QFileInfo docInfo(docPath);
    if (docInfo.size() / 1024 / 1024 > 100) {
        res = true;
    }

    return res;
}

QString EParserDocument::getFileIconData(const QString &docPath)
{
    if (docPath.isEmpty())
        return QString();

    QFileInfo docInfo(docPath);
    if (!docInfo.exists())
        return QString();

    QStringList suffixReplace;
    suffixReplace << "docx"
                  << "xlsx"
                  << "pptx";

    if (suffixReplace.contains(docInfo.suffix())) {
        // 文档后缀带x会获取到压缩包图标，需要去掉x: *.docx -> *.doc
        QString replaceXDocPath = docPath;
        replaceXDocPath.remove(replaceXDocPath.size() - 1, 1);
        docInfo.setFile(replaceXDocPath);
    }

    DFileIconProvider docIcon;
    QIcon idcon = docIcon.icon(docInfo);
    QImage image = idcon.pixmap(16, 16).toImage();
    QByteArray data;
    QBuffer buffer(&data);
    buffer.open(QIODevice::WriteOnly);
    image.save(&buffer, "PNG");
    buffer.close();

    return QString::fromLatin1(data.toBase64());
}
