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

class TestItemStore : public QObject
{
    Q_OBJECT

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

    void testItemStoreCreation()
    {
        ItemStore store;
        
        // Should start empty
        QVERIFY(store.getItems()->empty());
    }

    void testItemStoreAddItem()
    {
        ItemStore store;
        
        std::shared_ptr<Item> item(new Item(1, "test_item", 0));
        
        ItemAddRequest request;
        request.type = ITEM_UPDATE_USER;
        request.payload = item;
        request.changes = ItemFieldChanges(true);
        
        store.addItem(request);
        
        // Item should be added
        QVERIFY(store.getItems()->size() == 1);
    }

    void testItemStoreAddMultipleItems()
    {
        ItemStore store;
        
        std::shared_ptr<Item> item1(new Item(1, "item1", 0));
        std::shared_ptr<Item> item2(new Item(2, "item2", 1));
        
        std::vector<ItemAddRequest> requests;
        
        ItemAddRequest request1;
        request1.type = ITEM_UPDATE_USER;
        request1.payload = item1;
        request1.changes = ItemFieldChanges(true);
        requests.push_back(request1);
        
        ItemAddRequest request2;
        request2.type = ITEM_UPDATE_USER;
        request2.payload = item2;
        request2.changes = ItemFieldChanges(true);
        requests.push_back(request2);
        
        store.addItems(requests);
        
        // Both items should be added
        QVERIFY(store.getItems()->size() == 2);
    }

    void testItemStoreGetItem()
    {
        ItemStore store;
        
        std::shared_ptr<Item> item(new Item(42, "test_item", 0));
        
        ItemAddRequest request;
        request.type = ITEM_UPDATE_USER;
        request.payload = item;
        request.changes = ItemFieldChanges(true);
        
        store.addItem(request);
        
        // Get item by id
        std::shared_ptr<Item> found = store.getItem(42);
        QVERIFY(found != nullptr);
        QVERIFY(found->getName() == "test_item");
        
        // Get non-existent item
        std::shared_ptr<Item> notFound = store.getItem(999);
        QVERIFY(notFound == nullptr);
    }

    void testItemStoreRemoveItem()
    {
        ItemStore store;
        
        std::shared_ptr<Item> item(new Item(1, "test_item", 0));
        
        ItemAddRequest request;
        request.type = ITEM_UPDATE_USER;
        request.payload = item;
        request.changes = ItemFieldChanges(true);
        
        store.addItem(request);
        QVERIFY(store.getItems()->size() == 1);
        
        // Remove item
        ItemData itemData(1, "test_item", 0);
        store.removeItem(itemData);
        
        QVERIFY(store.getItems()->empty());
    }

    void testItemStoreClear()
    {
        ItemStore store;
        
        // Add multiple items
        for (int i = 0; i < 5; i++) {
            std::shared_ptr<Item> item(new Item(i, "item" + QString::number(i), 0));
            ItemAddRequest request;
            request.type = ITEM_UPDATE_USER;
            request.payload = item;
            request.changes = ItemFieldChanges(true);
            store.addItem(request);
        }
        
        QVERIFY(store.getItems()->size() == 5);
        
        // Clear all items
        store.clear();
        
        QVERIFY(store.getItems()->empty());
    }

    void testItemStoreUpdateItem()
    {
        ItemStore store;
        
        std::shared_ptr<Item> item(new Item(1, "test_item", 0));
        
        ItemAddRequest request;
        request.type = ITEM_UPDATE_USER;
        request.payload = item;
        request.changes = ItemFieldChanges(true);
        
        store.addItem(request);
        
        // Update item value
        ItemUpdateRequest update;
        update.type = ITEM_UPDATE_USER;
        ItemData updatedData(1, "test_item", 1); // value = 1
        update.payload = updatedData;
        update.changes.value = true;
        
        store.updateItem(update);
        
        // Verify value was updated
        std::shared_ptr<Item> found = store.getItem(1);
        QVERIFY(found->getValue() == 1);
    }

    void testItemStoreUpdateMultipleItems()
    {
        ItemStore store;
        
        // Add items
        for (int i = 0; i < 3; i++) {
            std::shared_ptr<Item> item(new Item(i, "item" + QString::number(i), 0));
            ItemAddRequest request;
            request.type = ITEM_UPDATE_USER;
            request.payload = item;
            request.changes = ItemFieldChanges(true);
            store.addItem(request);
        }
        
        // Update multiple items
        std::vector<ItemUpdateRequest> updates;
        
        for (int i = 0; i < 3; i++) {
            ItemUpdateRequest update;
            update.type = ITEM_UPDATE_USER;
            ItemData data(i, "item" + QString::number(i), 1);
            update.payload = data;
            update.changes.value = true;
            updates.push_back(update);
        }
        
        store.updateItems(updates);
        
        // Verify all values were updated
        for (int i = 0; i < 3; i++) {
            std::shared_ptr<Item> found = store.getItem(i);
            QVERIFY(found->getValue() == 1);
        }
    }

    void testItemStoreJsonSerialization()
    {
        ItemStore store;
        
        // Add items
        for (int i = 0; i < 2; i++) {
            std::shared_ptr<Item> item(new Item(i, "item" + QString::number(i), i));
            item->setGroupName("TestGroup");
            ItemAddRequest request;
            request.type = ITEM_UPDATE_USER;
            request.payload = item;
            request.changes = ItemFieldChanges(true);
            store.addItem(request);
        }
        
        // Serialize to JSON
        QJsonObject json;
        store.store(json);
        
        // Verify JSON contains items array
        QVERIFY(json.contains("Items"));
        QVERIFY(json["Items"].toArray().size() == 2);
    }

    void testItemStoreReplaceItems()
    {
        ItemStore store;
        
        // Add initial items
        std::shared_ptr<Item> item1(new Item(1, "item1", 0));
        ItemAddRequest request1;
        request1.type = ITEM_UPDATE_USER;
        request1.payload = item1;
        request1.changes = ItemFieldChanges(true);
        store.addItem(request1);
        
        QVERIFY(store.getItems()->size() == 1);
        
        // Replace with new items
        std::vector<std::shared_ptr<Item>> newItems;
        newItems.push_back(std::shared_ptr<Item>(new Item(2, "new_item1", 0)));
        newItems.push_back(std::shared_ptr<Item>(new Item(3, "new_item2", 1)));
        
        store.replaceItems(newItems);
        
        // Should have new items
        QVERIFY(store.getItems()->size() == 2);
        
        // Old item should be removed
        QVERIFY(store.getItem(1) == nullptr);
    }

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

QTEST_APPLESS_MAIN(TestItemStore)

#include "test_itemstore.moc"