#ifndef EDITSCENE_INVENTORY_HPP
#define EDITSCENE_INVENTORY_HPP
#pragma once

#include <Ogre.h>
#include <flecs.h>
#include <vector>
#include <string>
#include <cstdint>

#include "../systems/ItemRegistry.hpp"

/**
 * A single slot in an inventory.
 * Stores a reference to an item entity (if the item is a world entity)
 * or stores item data directly for items that exist only in inventory.
 */
struct InventorySlot {
	// Flecs entity ID of the item (0 if slot is empty or no world entity)
	flecs::entity_t itemEntity = 0;

	// Item registry key
	std::string itemId;

	// Stack size
	int stackSize = 0;

	bool isEmpty() const
	{
		return itemId.empty() && itemEntity == 0;
	}

	void clear()
	{
		itemEntity = 0;
		itemId.clear();
		stackSize = 0;
	}
};

/**
 * Inventory component.
 *
 * Attached to a character entity to hold items.
 * Can also be attached to container entities (chests, barrels, etc.)
 * to define their contents.
 */
struct InventoryComponent {
	// Maximum number of slots
	int maxSlots = 20;

	// Current slots
	std::vector<InventorySlot> slots;

	// Total weight of all items (computed)
	float totalWeight = 0.0f;

	// Maximum weight capacity (0 = unlimited)
	float maxWeight = 50.0f;

	// Whether this inventory is a container (chest, barrel, etc.)
	bool isContainer = false;

	// Whether this inventory is currently open (for containers being browsed)
	bool isOpen = false;

	// Persistent ID for scene containers (empty for character inventories)
	std::string containerId;

	InventoryComponent() = default;

	explicit InventoryComponent(int maxSlots_)
		: maxSlots(maxSlots_)
	{
		slots.reserve(maxSlots_);
	}

	/** Find the first empty slot index, or -1 if full. */
	int findEmptySlot() const
	{
		for (int i = 0; i < maxSlots; i++) {
			if (i >= (int)slots.size())
				return i;
			if (slots[i].isEmpty())
				return i;
		}
		return -1;
	}

	/** Find a slot containing an item with the given itemId. */
	int findItem(const std::string &itemId) const
	{
		for (int i = 0; i < (int)slots.size(); i++) {
			if (!slots[i].isEmpty() && slots[i].itemId == itemId)
				return i;
		}
		return -1;
	}

	/** Count total number of items (sum of stack sizes). */
	int countItems() const
	{
		int count = 0;
		for (const auto &slot : slots) {
			if (!slot.isEmpty())
				count += slot.stackSize;
		}
		return count;
	}

	/** Count how many of a specific itemId are in the inventory. */
	int countItem(const std::string &itemId) const
	{
		int count = 0;
		for (const auto &slot : slots) {
			if (!slot.isEmpty() && slot.itemId == itemId)
				count += slot.stackSize;
		}
		return count;
	}

	/** Check if inventory has at least one of a specific itemId. */
	bool hasItem(const std::string &itemId) const
	{
		return findItem(itemId) >= 0;
	}

	/** Recalculate total weight from registry. */
	void recalculateWeight()
	{
		totalWeight = 0.0f;
		for (const auto &slot : slots) {
			if (!slot.isEmpty())
				totalWeight +=
					ItemRegistry::getSingleton().getWeight(slot.itemId) *
					slot.stackSize;
		}
	}
};

#endif // EDITSCENE_INVENTORY_HPP
