#include <QtTest/QtTest>
#include "items/itemloadersource.h"
#include "items/item.h"

class TestItemLoaderSource : public QObject
{
    Q_OBJECT

private slots:
    void initTestCase()
    {
        // Setup for all tests
    }

    void testItemLoaderSourceCreation()
    {
        ItemLoaderSource source;
        
        // Should be created with empty JSON
        QVERIFY(true); // No crash
    }

    void testItemLoaderSourceCreationWithJson()
    {
        QJsonObject json;
        json["Items"] = QJsonArray();
        
        ItemLoaderSource source(json);
        
        // Should be created with JSON
        QVERIFY(true); // No crash
    }

    void testItemLoaderSourceRefreshEmpty()
    {
        ItemLoaderSource source;
        
        // Should not crash with empty JSON
        source.refresh();
        
        // No items should be emitted
        QVERIFY(true);
    }

    void testItemLoaderSourceRefreshWithItems()
    {
        QJsonObject json;
        QJsonArray itemsArray;
        
        QJsonObject item1;
        item1["Type"] = "Item";
        item1["ItemId"] = 1;
        item1["Name"] = "test_item1";
        item1["Value"] = 0;
        itemsArray.append(item1);
        
        QJsonObject item2;
        item2["Type"] = "Item";
        item2["ItemId"] = 2;
        item2["Name"] = "test_item2";
        item2["Value"] = 1;
        itemsArray.append(item2);
        
        json["Items"] = itemsArray;
        
        ItemLoaderSource source(json);
        
        // Capture the gotItems signal
        std::vector<ItemAddRequest> capturedItems;
        connect(&source, &ItemLoaderSource::gotItems, 
                [&capturedItems](std::vector<ItemAddRequest> items) {
            capturedItems = items;
        });
        
        source.refresh();
        
        // Should have 2 items
        QVERIFY(capturedItems.size() == 2);
    }

    void testItemLoaderSourceRefreshWithRelay()
    {
        QJsonObject json;
        QJsonArray itemsArray;
        
        QJsonObject relay;
        relay["Type"] = "Relay";
        relay["ItemId"] = 100;
        relay["Name"] = "test_relay";
        relay["Value"] = 0;
        relay["Id"] = 1;
        relay["Address"] = 0x2000;
        itemsArray.append(relay);
        
        json["Items"] = itemsArray;
        
        ItemLoaderSource source(json);
        
        // Capture the gotItems signal
        std::vector<ItemAddRequest> capturedItems;
        connect(&source, &ItemLoaderSource::gotItems, 
                [&capturedItems](std::vector<ItemAddRequest> items) {
            capturedItems = items;
        });
        
        source.refresh();
        
        // Should have 1 item
        QVERIFY(capturedItems.size() == 1);
    }

    void testItemLoaderSourceUpdateJson()
    {
        ItemLoaderSource source;
        
        // Initial JSON
        QJsonObject json1;
        QJsonArray items1;
        QJsonObject item1;
        item1["Type"] = "Item";
        item1["ItemId"] = 1;
        item1["Name"] = "item1";
        items1.append(item1);
        json1["Items"] = items1;
        
        source.updateJson(json1);
        
        // Update JSON
        QJsonObject json2;
        QJsonArray items2;
        QJsonObject item2;
        item2["Type"] = "Item";
        item2["ItemId"] = 2;
        item2["Name"] = "item2";
        items2.append(item2);
        json2["Items"] = items2;
        
        source.updateJson(json2);
        
        // Should not crash
        QVERIFY(true);
    }

    void testItemLoaderSourceRefreshWithInvalidItems()
    {
        QJsonObject json;
        QJsonArray itemsArray;
        
        // Add invalid item (no Type)
        QJsonObject item1;
        item1["ItemId"] = 1;
        itemsArray.append(item1);
        
        json["Items"] = itemsArray;
        
        ItemLoaderSource source(json);
        
        // Capture the gotItems signal
        std::vector<ItemAddRequest> capturedItems;
        connect(&source, &ItemLoaderSource::gotItems, 
                [&capturedItems](std::vector<ItemAddRequest> items) {
            capturedItems = items;
        });
        
        source.refresh();
        
        // Should handle invalid item gracefully (may return 0 items)
        QVERIFY(capturedItems.size() == 0 || capturedItems.size() == 1);
    }

    void testItemLoaderSourceRefreshWithMessageItem()
    {
        QJsonObject json;
        QJsonArray itemsArray;
        
        QJsonObject messageItem;
        messageItem["Type"] = "Message";
        messageItem["ItemId"] = 200;
        messageItem["Name"] = "alert_item";
        messageItem["Value"] = 0;
        messageItem["Message"] = "Test message";
        itemsArray.append(messageItem);
        
        json["Items"] = itemsArray;
        
        ItemLoaderSource source(json);
        
        // Capture the gotItems signal
        std::vector<ItemAddRequest> capturedItems;
        connect(&source, &ItemLoaderSource::gotItems, 
                [&capturedItems](std::vector<ItemAddRequest> items) {
            capturedItems = items;
        });
        
        source.refresh();
        
        // Should have 1 item
        QVERIFY(capturedItems.size() == 1);
    }

    void testItemLoaderSourceRefreshWithSystemItem()
    {
        QJsonObject json;
        QJsonArray itemsArray;
        
        QJsonObject systemItem;
        systemItem["Type"] = "System";
        systemItem["ItemId"] = 300;
        systemItem["Name"] = "system_item";
        systemItem["Value"] = 0;
        systemItem["OnCommand"] = "echo on";
        systemItem["OffCommand"] = "echo off";
        itemsArray.append(systemItem);
        
        json["Items"] = itemsArray;
        
        ItemLoaderSource source(json);
        
        // Capture the gotItems signal
        std::vector<ItemAddRequest> capturedItems;
        connect(&source, &ItemLoaderSource::gotItems, 
                [&capturedItems](std::vector<ItemAddRequest> items) {
            capturedItems = items;
        });
        
        source.refresh();
        
        // Should have 1 item
        QVERIFY(capturedItems.size() == 1);
    }

    void cleanupTestCase()
    {
        // Cleanup after all tests
    }
};

QTEST_APPLESS_MAIN(TestItemLoaderSource)

#include "test_itemloadersource.moc"