/*******************************************************************
 * SPDX-FileCopyrightText: 2009 Dario Andres Rodriguez <andresbajotierra@gmail.com>
 * SPDX-FileCopyrightText: 2009 A. L. Spehr <spehr@kde.org>
 * SPDX-FileCopyrightText: 2021 Harald Sitter <sitter@kde.org>
 * SPDX-License-Identifier: GPL-2.0-or-later
 ******************************************************************/

#include "assistantpage_conclusion.h"

#include <QDesktopServices>
#include <QUrl>

#include <kio_version.h>
#if KIO_VERSION >= QT_VERSION_CHECK(5, 89, 0)
#include <KEMailClientLauncherJob>
#endif
#include <KLocalizedString>
#include <KToolInvocation>

#include "backtracegenerator.h"
#include "crashedapplication.h"
#include "debuggermanager.h"
#include "drkonqi.h"
#include "drkonqi_debug.h"
#include "parser/backtraceparser.h"
#include "reportinformationdialog.h"
#include "reportinterface.h"

ConclusionPage::ConclusionPage(ReportAssistantDialog *parent)
    : ReportAssistantPage(parent)
    , m_needToReport(false)
{
    m_isBKO = DrKonqi::crashedApplication()->bugReportAddress().isKdeBugzilla();

    ui.setupUi(this);

    KGuiItem::assign(ui.m_showReportInformationButton,
                     KGuiItem2(i18nc("@action:button", "&Show Contents of the Report"),
                               QIcon::fromTheme(QStringLiteral("document-preview")),
                               i18nc("@info:tooltip",
                                     "Use this button to show the generated "
                                     "report information about this crash.")));
    connect(ui.m_showReportInformationButton, &QPushButton::clicked, this, &ConclusionPage::openReportInformation);

    connect(ui.m_explanationLabel, &QLabel::linkActivated, this, [](const QString &link) {
        QDesktopServices::openUrl(QUrl(link));
    });

    KGuiItem::assign(ui.m_appRestartButton, DrStandardGuiItem::appRestart());
    connect(ui.m_appRestartButton, &QAbstractButton::clicked, DrKonqi::crashedApplication(), &CrashedApplication::restart);
    connect(DrKonqi::crashedApplication(), &CrashedApplication::restarted, this, [this](bool restarted) {
        ui.m_appRestartButton->setEnabled(!restarted);
    });
    ui.m_appRestartButton->setVisible(false);
}

void ConclusionPage::finishClicked()
{
    // Manual report
    if (m_needToReport && !m_isBKO) {
        const CrashedApplication *crashedApp = DrKonqi::crashedApplication();
        BugReportAddress reportAddress = crashedApp->bugReportAddress();
        QString report = reportInterface()->generateReportFullText(ReportInterface::DrKonqiStamp::Exclude, ReportInterface::Backtrace::Complete);

        if (reportAddress.isEmail()) {
            QString subject = QStringLiteral("[%1] [%2] Automatic crash report generated by DrKonqi");
            subject = subject.arg(crashedApp->name());
            subject = subject.arg(crashedApp->datetime().toString(QStringLiteral("yyyy-MM-dd")));
#if KIO_VERSION >= QT_VERSION_CHECK(5, 89, 0)
            KEMailClientLauncherJob *job = new KEMailClientLauncherJob(this);
            job->setSubject(subject);
            job->setTo({reportAddress});
            job->setBody(report);
            job->start();
#else

            KToolInvocation::invokeMailer(reportAddress, QLatin1String(""), QLatin1String(""), subject, report);
#endif
        } else {
            QUrl url(reportAddress);
            if (QUrl(reportAddress).isRelative()) { // Scheme is missing
                url = QUrl(QString::fromLatin1("https://%1").arg(reportAddress));
            }
            QDesktopServices::openUrl(url);
        }

        // Show a copy of the bug reported
        openReportInformation();
    }
}

void ConclusionPage::aboutToShow()
{
    ui.m_appRestartButton->setVisible(!DrKonqi::crashedApplication()->hasBeenRestarted());
    connect(assistant()->finishButton(), &QPushButton::clicked, this, &ConclusionPage::finishClicked);

    const bool isDuplicate = reportInterface()->duplicateId() && !reportInterface()->attachToBugNumber();
    m_needToReport = reportInterface()->isWorthReporting() && !isDuplicate;
    emitCompleteChanged();

    if (DrKonqi::debuggerManager()->backtraceGenerator()->parser()->hasCompositorCrashed()) {
        ui.m_conclusionsLabel->setText(i18nc("@info",
                                             "It appears that this crash is actually the result of an earlier crash in the compositor and cannot be "
                                             "submitted as it lacks the required information to resolve the problem."));
        ui.m_explanationLabel->setText(xi18nc(
            "@info",
            "KDE developers would appreciate if you could find and attach the crash log for the compositor. You may be able to retrieve it using the "
            "coredumpctl utility. For more information, see "
            "<link "
            "url='https://community.kde.org/Guidelines_and_HOWTOs/Debugging/How_to_create_useful_crash_reports#Retrieving_a_backtrace_using_coredumpctl'>the "
            "KDE Community Wiki</"
            "link>."));
        ui.m_showReportInformationButton->setVisible(false); // Don't give access to the report, lest people file them manually.
        Q_EMIT finished(false /* don't enable back button - the user can't improve this result*/);
        return;
    }

    BugReportAddress reportAddress = DrKonqi::crashedApplication()->bugReportAddress();
    BacktraceParser::Usefulness use = DrKonqi::debuggerManager()->backtraceGenerator()->parser()->backtraceUsefulness();

    QString explanationHTML = QLatin1String("<p><ul>");

    bool backtraceGenerated = true;
    switch (use) {
    case BacktraceParser::ReallyUseful: {
        explanationHTML += QStringLiteral("<li>%1</li>")
                               .arg(i18nc("@info",
                                          "The automatically generated "
                                          "crash information is useful."));
        break;
    }
    case BacktraceParser::MayBeUseful: {
        explanationHTML += QStringLiteral("<li>%1</li>")
                               .arg(i18nc("@info",
                                          "The automatically generated "
                                          "crash information lacks some "
                                          "details "
                                          "but may be still be useful."));
        break;
    }
    case BacktraceParser::ProbablyUseless: {
        explanationHTML += QStringLiteral("<li>%1</li>")
                               .arg(i18nc("@info",
                                          "The automatically generated "
                                          "crash information lacks important details "
                                          "and it is probably not helpful."));
        break;
    }
    case BacktraceParser::Useless:
    case BacktraceParser::InvalidUsefulness: {
        BacktraceGenerator::State state = DrKonqi::debuggerManager()->backtraceGenerator()->state();
        if (state == BacktraceGenerator::NotLoaded) {
            backtraceGenerated = false;
            explanationHTML += QStringLiteral("<li>%1</li>")
                                   .arg(i18nc("@info",
                                              "The crash information was "
                                              "not generated because it was not needed."));
        } else {
            explanationHTML += QStringLiteral("<li>%1<br />%2</li>")
                                   .arg(i18nc("@info",
                                              "The automatically generated crash "
                                              "information does not contain enough information to be "
                                              "helpful."),
                                        xi18nc("@info",
                                               "<note>You can improve it by "
                                               "installing debugging packages and reloading the crash on "
                                               "the Crash Information page. You can get help with the Bug "
                                               "Reporting Guide by clicking on the "
                                               "<interface>Help</interface> button.</note>"));
            // but this guide doesn't mention bt packages? that's techbase
            //->>and the help guide mention techbase page...
        }
        break;
    }
    }

    // User can provide enough information
    if (reportInterface()->isBugAwarenessPageDataUseful()) {
        explanationHTML += QStringLiteral("<li>%1</li>")
                               .arg(i18nc("@info",
                                          "The information you can "
                                          "provide could be considered helpful."));
    } else {
        explanationHTML += QStringLiteral("<li>%1</li>")
                               .arg(i18nc("@info",
                                          "The information you can "
                                          "provide is not considered helpful enough in this case."));
    }

    if (isDuplicate) {
        explanationHTML += QStringLiteral("<li>%1</li>")
                               .arg(xi18nc("@info",
                                           "Your problem has already been "
                                           "reported as bug %1.",
                                           QString::number(reportInterface()->duplicateId())));
    }

    explanationHTML += QLatin1String("</ul></p>");

    ui.m_explanationLabel->setText(explanationHTML);

    // Hide the "Show contents of the report" button if the backtrace was not generated
    ui.m_showReportInformationButton->setVisible(backtraceGenerated);

    if (m_needToReport) {
        ui.m_conclusionsLabel->setText(QStringLiteral("<p><strong>%1</strong>")
                                           .arg(i18nc("@info",
                                                      "This "
                                                      "report is considered helpful.")));

        if (m_isBKO) {
            emitCompleteChanged();
            ui.m_howToProceedLabel->setText(xi18nc("@info",
                                                   "This application's bugs are reported "
                                                   "to the KDE bug tracking system: click <interface>Next"
                                                   "</interface> to start the reporting process. "
                                                   "You can manually report at <link>%1</link>",
                                                   reportAddress));

        } else {
            ui.m_howToProceedLabel->setText(xi18nc("@info",
                                                   "This application is not supported in the "
                                                   "KDE bug tracking system. Click <interface>"
                                                   "Finish</interface> to report this bug to "
                                                   "the application maintainer. Also, you can manually "
                                                   "report at <link>%1</link>.",
                                                   reportAddress));

            Q_EMIT finished(false);
        }

    } else { // (m_needToReport)
        ui.m_conclusionsLabel->setText(QStringLiteral("<p><strong>%1</strong><br />%2</p>")
                                           .arg(i18nc("@info",
                                                      "This report does not contain enough information for the "
                                                      "developers, so the automated bug reporting process is not "
                                                      "enabled for this crash."),
                                                i18nc("@info",
                                                      "If you wish, you can go back and change your "
                                                      "answers. ")));

        // Only mention "manual reporting" if the backtrace was generated.
        // FIXME separate the texts "manual reporting" / "click finish to close"
        //"manual reporting" should be ~"manual report using the contents of the report"....
        // FIXME for 4.5 (workflow, see ToDo)
        if (backtraceGenerated) {
            if (m_isBKO) {
                ui.m_howToProceedLabel->setText(xi18nc("@info",
                                                       "You can manually report this bug "
                                                       "at <link>%1</link>. "
                                                       "Click <interface>Finish</interface> to close the "
                                                       "assistant.",
                                                       reportAddress));
            } else {
                ui.m_howToProceedLabel->setText(xi18nc("@info",
                                                       "You can manually report this "
                                                       "bug to its maintainer at <link>%1</link>. "
                                                       "Click <interface>Finish</interface> to close the "
                                                       "assistant.",
                                                       reportAddress));
            }
        }
        Q_EMIT finished(true);
    }
}

void ConclusionPage::aboutToHide()
{
    disconnect(assistant()->finishButton(), &QPushButton::clicked, this, &ConclusionPage::finishClicked);
}

void ConclusionPage::openReportInformation()
{
    if (!m_infoDialog) {
        QString info = reportInterface()->generateReportFullText(ReportInterface::DrKonqiStamp::Exclude, ReportInterface::Backtrace::Complete)
            + QLatin1Char('\n') + i18nc("@info report to url/mail address", "Report to %1", DrKonqi::crashedApplication()->bugReportAddress());

        m_infoDialog = new ReportInformationDialog(info);
    }
    m_infoDialog->show();
    m_infoDialog->raise();
    m_infoDialog->activateWindow();
}

bool ConclusionPage::isComplete()
{
    return (m_isBKO && m_needToReport);
}

bool ConclusionPage::isAppropriate()
{
    if (!(reportInterface()->isBugAwarenessPageDataUseful())) {
        qCDebug(DRKONQI_LOG) << "not aware enough";
        return true;
    }
    if (DrKonqi::debuggerManager()->backtraceGenerator()->parser()->hasCompositorCrashed()) {
        qCDebug(DRKONQI_LOG) << "compositor crashed";
        return true;
    }
    if (!DrKonqi::crashedApplication()->bugReportAddress().isKdeBugzilla()) {
        qCDebug(DRKONQI_LOG) << "not bugzilla";
        return true;
    }
    if (DrKonqi::debuggerManager()->backtraceGenerator()->state() != BacktraceGenerator::NotLoaded && !reportInterface()->isWorthReporting()) {
        qCDebug(DRKONQI_LOG) << "not worth reporting";
        return true;
    }
    if (reportInterface()->duplicateId() && !reportInterface()->attachToBugNumber()) {
        qCDebug(DRKONQI_LOG) << "is a dupe";
        return true;
    }
    return false;
}
