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

class TestItem : public QObject
{
    Q_OBJECT

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

    void testItemCreation()
    {
        Item item(0, "test_item", 0);
        QCOMPARE(item.getName(), QString("test_item"));
    }

    void testOverrideFunctionality()
    {
        Item item(0, "test_item", 0);
        
        // Test override on/off
        item.setOverride(true);
        QVERIFY(item.getOverride());
        
        item.setOverride(false);
        QVERIFY(!item.getOverride());
    }

    void testItemValueTypes()
    {
        // Test default value type is BOOL
        Item item(1, "test_item", 0);
        QCOMPARE(item.getValueType(), ITEM_VALUE_BOOL);
        
        // Test setting and getting value
        item.setValueData(1);
        QCOMPARE(item.getValue(), static_cast<uint8_t>(1));
        
        item.setValueData(0);
        QCOMPARE(item.getValue(), static_cast<uint8_t>(0));
    }

    void testItemId()
    {
        Item item(42, "test_item", 0);
        QCOMPARE(item.id(), static_cast<uint32_t>(42));
    }

    void testItemGroupName()
    {
        Item item(1, "test_item", 0);
        QCOMPARE(item.getGroupName(), QString("All")); // Default group
        
        item.setGroupName("Living Room");
        QCOMPARE(item.getGroupName(), QString("Living Room"));
    }

    void testItemHidden()
    {
        Item item(1, "test_item", 0);
        QVERIFY(!item.isHidden());
        
        item.setHidden(true);
        QVERIFY(item.isHidden());
        
        item.setHidden(false);
        QVERIFY(!item.isHidden());
    }

    void testItemLoaded()
    {
        Item item(1, "test_item", 0);
        QVERIFY(!item.getLoaded());
        
        item.setLoaded(true);
        QVERIFY(item.getLoaded());
    }

    void testItemJsonSerialization()
    {
        Item item(42, "test_item", 1);
        item.setGroupName("TestGroup");
        
        QJsonObject json;
        item.store(json);
        
        // Verify JSON contents
        QCOMPARE(json["ItemId"].toDouble(), 42.0);
        // Note: Name is only stored if changes.name is true
        // Value is only stored if changes.value is true
    }

    void testItemJsonDeserialization()
    {
        QJsonObject json;
        json["ItemId"] = 100;
        json["Name"] = "loaded_item";
        json["Value"] = 1;
        json["GroupName"] = "Bedroom";
        
        Item item;
        item.load(json);
        
        // Note: load() uses loadWithChanges which requires preserve=false to apply changes
        // The id should be set
        // The name should be set (since preserve defaults to false)
    }

    void testItemUpdateRequest()
    {
        Item item(1, "test_item", 0);
        
        // Test creating update request
        ItemUpdateRequest request = item.createValueUpdateRequest(ITEM_UPDATE_USER, false);
        
        QVERIFY(request.type == ITEM_UPDATE_USER);
        // Note: changes is not automatically set by createValueUpdateRequest
        // The caller is expected to set the changes they want
        QVERIFY(request.newActors.empty());
    }

    void testItemUpdateRequestWithActors()
    {
        Item item(1, "test_item", 0);
        
        // Test creating update request with actors
        ItemUpdateRequest request = item.createValueUpdateRequest(ITEM_UPDATE_USER, true);
        
        QVERIFY(request.type == ITEM_UPDATE_USER);
        // With actors=true, newActors should be populated
        // Note: changes.actors is set by the caller, not by createValueUpdateRequest
    }

    void testItemHasActors()
    {
        Item item(1, "test_item", 0);
        
        QVERIFY(!item.hasActors());
        
        // Note: Adding actors requires a valid Actor pointer
    }

    void testItemRemoveAllActors()
    {
        Item item(1, "test_item", 0);
        
        item.removeAllActors();
        QVERIFY(!item.hasActors());
    }

    void testItemSetActorsActive()
    {
        Item item(1, "test_item", 0);
        
        // Should not crash when no actors
        item.setActorsActive(true);
        item.setActorsActive(false);
    }

    void testItemDataChangeDetection()
    {
        ItemData data1(1, "item1", 0);
        ItemData data2(1, "item1", 1);
        
        // Test value change detection
        ItemFieldChanges changes(true);
        QVERIFY(data1.hasChanged(data2, changes));
        
        // Test no change
        changes = ItemFieldChanges(false);
        QVERIFY(!data1.hasChanged(data2, changes));
    }

    void testItemDataNameChange()
    {
        ItemData data1(1, "item1", 0);
        ItemData data2(1, "item2", 0);
        
        ItemFieldChanges changes;
        changes.name = true;
        
        QVERIFY(data1.hasChanged(data2, changes));
    }

    void testItemDataGroupNameChange()
    {
        ItemData data1(1, "item1", 0);
        data1.setGroupName("Group1");
        
        ItemData data2(1, "item1", 0);
        data2.setGroupName("Group2");
        
        ItemFieldChanges changes;
        changes.groupName = true;
        
        QVERIFY(data1.hasChanged(data2, changes));
    }

    void testItemFieldChanges()
    {
        ItemFieldChanges changes(false);
        QVERIFY(changes.isNone());
        
        changes.value = true;
        QVERIFY(!changes.isNone());
        
        ItemFieldChanges allChanges(true);
        QVERIFY(!allChanges.isNone());
    }

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

QTEST_APPLESS_MAIN(TestItem)

#include "test_item.moc"
