#include <QApplication>
#include <QImage>
#include <QIcon>
#include <QPixmap>
#include <QTemporaryDir>
#include <QtTest>

#include "icon-helper.h"

using namespace UkuiQuick;

namespace {

class ThemeGuard
{
public:
    ThemeGuard()
        : m_themeName(QIcon::themeName())
        , m_searchPaths(QIcon::themeSearchPaths())
    {
    }

    ~ThemeGuard()
    {
        QIcon::setThemeName(m_themeName);
        QIcon::setThemeSearchPaths(m_searchPaths);
    }

private:
    QString m_themeName;
    QStringList m_searchPaths;
};

QString writeThemeIcon(QTemporaryDir &dir, const QString &themeName, const QString &iconName, const QColor &color)
{
    const QString rootPath = dir.filePath(themeName);
    const QString iconDir = rootPath + QStringLiteral("/48x48/apps");
    QDir().mkpath(iconDir);

    QFile index(rootPath + QStringLiteral("/index.theme"));
    index.open(QIODevice::WriteOnly | QIODevice::Truncate);
    index.write(
        QStringLiteral(
            "[Icon Theme]\n"
            "Name=%1\n"
            "Directories=48x48/apps\n"
            "\n"
            "[48x48/apps]\n"
            "Size=48\n"
            "Context=Applications\n"
            "Type=Fixed\n")
            .arg(themeName)
            .toUtf8());
    index.close();

    const QString iconPath = iconDir + QLatin1Char('/') + iconName + QStringLiteral(".png");
    QImage image(8, 8, QImage::Format_ARGB32);
    image.fill(color);
    image.save(iconPath);
    return iconPath;
}

QColor centerColor(const QIcon &icon)
{
    const QImage image = icon.pixmap(16, 16).toImage();
    return image.pixelColor(image.width() / 2, image.height() / 2);
}

}

class icon_helper_test : public QObject
{
    Q_OBJECT

private slots:
    void toLocalPathRecognizesSupportedLocalForms();
    void toLocalPathRejectsUnsupportedForms();
    void fileTypePredicatesClassifyUrls();
    void loadPixmapLoadsExistingImagesOnly();
    void emptyIdUsesDefaultIcon();
    void loadIconUsesLocalFileAndFallsBackWhenMissing();
    void defaultIconFallsBackToResourceWhenThemeMissing();
    void themeLookupRecognizesCustomThemeIcons();
    void themeLookupRejectsMissingIconName();
};

void icon_helper_test::toLocalPathRecognizesSupportedLocalForms()
{
    QCOMPARE(IconHelper::toLocalPath(QUrl::fromLocalFile("/tmp/test-icon.png")), QStringLiteral("/tmp/test-icon.png"));
    QCOMPARE(IconHelper::toLocalPath(QUrl(QStringLiteral("qrc:///res/icon/application-x-desktop.png"))),
             QStringLiteral(":/res/icon/application-x-desktop.png"));
    QCOMPARE(IconHelper::toLocalPath(QUrl(QStringLiteral("/absolute/icon.png"))), QStringLiteral("/absolute/icon.png"));
    QCOMPARE(IconHelper::toLocalPath(QUrl(QStringLiteral(":/res/icon/application-x-desktop.png"))),
             QStringLiteral(":/res/icon/application-x-desktop.png"));
}

void icon_helper_test::toLocalPathRejectsUnsupportedForms()
{
    QCOMPARE(IconHelper::toLocalPath(QUrl()), QString());
    QCOMPARE(IconHelper::toLocalPath(QUrl(QStringLiteral("relative/icon.png"))), QString());
    QCOMPARE(IconHelper::toLocalPath(QUrl(QStringLiteral("https://example.com/icon.png"))), QString());
    QCOMPARE(IconHelper::toLocalPath(QUrl(QStringLiteral("ftp://example.com/icon.png"))), QString());
}

void icon_helper_test::fileTypePredicatesClassifyUrls()
{
    QVERIFY(IconHelper::isLocalFile(QUrl::fromLocalFile("/tmp/test-icon.png")));
    QVERIFY(IconHelper::isLocalFile(QUrl(QStringLiteral("qrc:///res/icon/application-x-desktop.png"))));
    QVERIFY(!IconHelper::isLocalFile(QUrl(QStringLiteral("relative/icon.png"))));
    QVERIFY(!IconHelper::isLocalFile(QUrl(QStringLiteral("https://example.com/icon.png"))));

    QVERIFY(IconHelper::isRemoteServerFile(QUrl(QStringLiteral("http://example.com/icon.png"))));
    QVERIFY(IconHelper::isRemoteServerFile(QUrl(QStringLiteral("https://example.com/icon.png"))));
    QVERIFY(!IconHelper::isRemoteServerFile(QUrl(QStringLiteral("ftp://example.com/icon.png"))));
    QVERIFY(!IconHelper::isRemoteServerFile(QUrl()));
}

void icon_helper_test::loadPixmapLoadsExistingImagesOnly()
{
    QTemporaryDir dir;
    QVERIFY(dir.isValid());

    const QString imagePath = dir.filePath(QStringLiteral("icon.png"));
    QImage image(4, 4, QImage::Format_ARGB32);
    image.fill(Qt::red);
    QVERIFY(image.save(imagePath));

    QPixmap pixmap;
    QVERIFY(IconHelper::loadPixmap(imagePath, pixmap));
    QVERIFY(!pixmap.isNull());

    QPixmap missingPixmap;
    QVERIFY(!IconHelper::loadPixmap(dir.filePath(QStringLiteral("missing.png")), missingPixmap));
    QVERIFY(missingPixmap.isNull());
}

void icon_helper_test::emptyIdUsesDefaultIcon()
{
    ThemeGuard guard;
    QTemporaryDir dir;
    QVERIFY(dir.isValid());
    writeThemeIcon(dir, QStringLiteral("codex-theme"), QStringLiteral("application-x-desktop"), QColor(Qt::blue));
    QIcon::setThemeSearchPaths({dir.path()});
    QIcon::setThemeName(QStringLiteral("codex-theme"));

    const QIcon icon = IconHelper::loadIcon(QString());

    QVERIFY(!icon.isNull());
    QCOMPARE(centerColor(icon), QColor(Qt::blue));
}

void icon_helper_test::loadIconUsesLocalFileAndFallsBackWhenMissing()
{
    ThemeGuard guard;
    QTemporaryDir dir;
    QVERIFY(dir.isValid());
    const QString localPath = dir.filePath(QStringLiteral("local.png"));
    QImage localImage(4, 4, QImage::Format_ARGB32);
    localImage.fill(Qt::green);
    QVERIFY(localImage.save(localPath));

    writeThemeIcon(dir, QStringLiteral("codex-theme"), QStringLiteral("application-x-desktop"), QColor(Qt::blue));
    QIcon::setThemeSearchPaths({dir.path()});
    QIcon::setThemeName(QStringLiteral("codex-theme"));

    const QIcon localIcon = IconHelper::loadIcon(localPath);
    const QIcon fallbackIcon = IconHelper::loadIcon(dir.filePath(QStringLiteral("missing.png")));

    QVERIFY(!localIcon.isNull());
    QVERIFY(!fallbackIcon.isNull());
    QCOMPARE(centerColor(localIcon), QColor(Qt::green));
    QCOMPARE(centerColor(fallbackIcon), QColor(Qt::blue));
}

void icon_helper_test::defaultIconFallsBackToResourceWhenThemeMissing()
{
    ThemeGuard guard;
    QIcon::setThemeSearchPaths({});
    QIcon::setThemeName(QStringLiteral("missing-codex-theme"));

    const QIcon icon = IconHelper::getDefaultIcon();

    QVERIFY(!icon.isNull());
}

void icon_helper_test::themeLookupRecognizesCustomThemeIcons()
{
    ThemeGuard guard;
    QTemporaryDir dir;
    QVERIFY(dir.isValid());
    writeThemeIcon(dir, QStringLiteral("codex-theme"), QStringLiteral("ukui-quick-autotest-themed"), QColor(Qt::yellow));
    QIcon::setThemeSearchPaths({dir.path()});
    QIcon::setThemeName(QStringLiteral("codex-theme"));

    QVERIFY(IconHelper::isThemeIcon(QStringLiteral("ukui-quick-autotest-themed")));

    const QIcon icon = IconHelper::loadIcon(QStringLiteral("ukui-quick-autotest-themed"));
    QVERIFY(!icon.isNull());
    QCOMPARE(centerColor(icon), QColor(Qt::yellow));
}

void icon_helper_test::themeLookupRejectsMissingIconName()
{
    QVERIFY(!IconHelper::isThemeIcon(QStringLiteral("ukui-quick-autotest-missing-icon-name")));
}

int main(int argc, char *argv[])
{
    qputenv("QT_QPA_PLATFORM", "offscreen");
    qputenv("QT_QPA_PLATFORMTHEME", "generic");

    QApplication app(argc, argv);
    icon_helper_test testCase;
    return QTest::qExec(&testCase, argc, argv);
}

#include "test-icon-helper.moc"
