import { expect } from "@esm-bundle/chai";
import { CharacterSheet } from "../../../src/ui/components/CharacterSheet.js";
import { Explorer } from "../../../src/units/Explorer.js";
import { InventoryManager } from "../../../src/managers/InventoryManager.js";
import { InventoryContainer } from "../../../src/models/InventoryContainer.js";
import { Item } from "../../../src/items/Item.js";
import vanguardDef from "../../../src/assets/data/classes/vanguard.json" with {
  type: "json",
};

// Import SkillTreeUI to register the custom element
import "../../../src/ui/components/SkillTreeUI.js";

describe("UI: CharacterSheet - Inventory Integration", () => {
  let element;
  let container;
  let testUnit;
  let inventoryManager;
  let mockItemRegistry;

  beforeEach(() => {
    container = document.createElement("div");
    document.body.appendChild(container);
    element = document.createElement("character-sheet");
    container.appendChild(element);

    // Create mock item registry
    mockItemRegistry = {
      get: (defId) => {
        const items = {
          "ITEM_RUSTY_BLADE": new Item({
            id: "ITEM_RUSTY_BLADE",
            name: "Rusty Blade",
            type: "WEAPON",
            stats: { attack: 3 },
          }),
          "ITEM_SCRAP_PLATE": new Item({
            id: "ITEM_SCRAP_PLATE",
            name: "Scrap Plate",
            type: "ARMOR",
            stats: { defense: 3 },
          }),
          "ITEM_HEALTH_POTION": new Item({
            id: "ITEM_HEALTH_POTION",
            name: "Health Potion",
            type: "CONSUMABLE",
            stats: {},
          }),
        };
        return items[defId] || null;
      },
    };

    // Create inventory manager
    const runStash = new InventoryContainer("RUN_LOOT");
    const hubStash = new InventoryContainer("HUB_VAULT");
    inventoryManager = new InventoryManager(mockItemRegistry, runStash, hubStash);

    // Create test Explorer unit
    testUnit = new Explorer("test-unit-1", "Test Vanguard", "CLASS_VANGUARD", vanguardDef);
    testUnit.classMastery["CLASS_VANGUARD"] = {
      level: 5,
      xp: 250,
      skillPoints: 2,
      unlockedNodes: [],
    };
    testUnit.recalculateBaseStats(vanguardDef);
    testUnit.currentHealth = 100;
    testUnit.maxHealth = 120;
    // Ensure loadout is initialized (should be done in constructor, but ensure it exists)
    if (!testUnit.loadout) {
      testUnit.loadout = {
        mainHand: null,
        offHand: null,
        body: null,
        accessory: null,
        belt: [null, null],
      };
    }
  });

  afterEach(() => {
    if (container.parentNode) {
      container.parentNode.removeChild(container);
    }
  });

  // Helper to wait for LitElement update
  async function waitForUpdate() {
    await element.updateComplete;
    await new Promise((resolve) => setTimeout(resolve, 10));
  }

  // Helper to query shadow DOM
  function queryShadow(selector) {
    return element.shadowRoot?.querySelector(selector);
  }

  function queryShadowAll(selector) {
    return element.shadowRoot?.querySelectorAll(selector) || [];
  }

  describe("CoA 1: inventoryManager property", () => {
    it("should accept inventoryManager as property", async () => {
      element.unit = testUnit;
      element.inventoryManager = inventoryManager;
      await waitForUpdate();

      expect(element.inventoryManager).to.equal(inventoryManager);
    });

    it("should work without inventoryManager (legacy mode)", async () => {
      element.unit = testUnit;
      element.inventory = [];
      await waitForUpdate();

      expect(element.inventoryManager).to.be.null;
      // Should still render
      const inventoryGrid = queryShadow(".inventory-grid");
      expect(inventoryGrid).to.exist;
    });
  });

  describe("CoA 2: rendering stash items", () => {
    it("should render items from runStash in DUNGEON mode", async () => {
      // Add items to run stash
      inventoryManager.runStash.addItem({
        uid: "ITEM_001",
        defId: "ITEM_RUSTY_BLADE",
        isNew: true,
        quantity: 1,
      });

      inventoryManager.runStash.addItem({
        uid: "ITEM_002",
        defId: "ITEM_SCRAP_PLATE",
        isNew: false,
        quantity: 1,
      });

      element.unit = testUnit;
      element.inventoryManager = inventoryManager;
      element.gameMode = "DUNGEON";
      element.activeTab = "INVENTORY";
      await waitForUpdate();

      const itemCards = queryShadowAll(".item-card");
      expect(itemCards.length).to.equal(2);
    });

    it("should render items from hubStash in HUB mode", async () => {
      // Add items to hub stash
      inventoryManager.hubStash.addItem({
        uid: "ITEM_001",
        defId: "ITEM_RUSTY_BLADE",
        isNew: true,
        quantity: 1,
      });

      element.unit = testUnit;
      element.inventoryManager = inventoryManager;
      element.gameMode = "HUB";
      element.activeTab = "INVENTORY";
      await waitForUpdate();

      const itemCards = queryShadowAll(".item-card");
      expect(itemCards.length).to.equal(1);
    });

    it("should convert ItemInstance to UI format with name and type", async () => {
      inventoryManager.runStash.addItem({
        uid: "ITEM_001",
        defId: "ITEM_RUSTY_BLADE",
        isNew: true,
        quantity: 1,
      });

      element.unit = testUnit;
      element.inventoryManager = inventoryManager;
      element.gameMode = "DUNGEON";
      element.activeTab = "INVENTORY";
      await waitForUpdate();

      const itemCard = queryShadow(".item-card");
      expect(itemCard).to.exist;
      expect(itemCard.getAttribute("title")).to.equal("Rusty Blade");
    });
  });

  describe("CoA 3: equipping items via inventoryManager", () => {
    it("should equip item using inventoryManager.equipItem", async () => {
      // Add item to stash
      const itemInstance = {
        uid: "ITEM_001",
        defId: "ITEM_RUSTY_BLADE",
        isNew: true,
        quantity: 1,
      };
      inventoryManager.runStash.addItem(itemInstance);

      element.unit = testUnit;
      element.inventoryManager = inventoryManager;
      element.gameMode = "DUNGEON";
      element.activeTab = "INVENTORY";
      element.selectedSlot = "WEAPON";
      await waitForUpdate();

      let equipEventFired = false;
      element.addEventListener("equip-item", () => {
        equipEventFired = true;
      });

      const itemCard = queryShadow(".item-card");
      itemCard.click();
      await waitForUpdate();

      expect(equipEventFired).to.be.true;
      // Item should be equipped to loadout
      expect(testUnit.loadout.mainHand).to.exist;
      expect(testUnit.loadout.mainHand.defId).to.equal("ITEM_RUSTY_BLADE");
      // Item should be removed from stash
      expect(inventoryManager.runStash.findItem("ITEM_001")).to.be.null;
    });

    it("should map legacy slot types to new slot types", async () => {
      const itemInstance = {
        uid: "ITEM_001",
        defId: "ITEM_RUSTY_BLADE",
        isNew: true,
        quantity: 1,
      };
      inventoryManager.runStash.addItem(itemInstance);

      element.unit = testUnit;
      element.inventoryManager = inventoryManager;
      element.gameMode = "DUNGEON";
      element.activeTab = "INVENTORY";
      element.selectedSlot = "WEAPON"; // Legacy slot type
      await waitForUpdate();

      const itemCard = queryShadow(".item-card");
      itemCard.click();
      await waitForUpdate();

      // Should equip to MAIN_HAND (mapped from WEAPON)
      expect(testUnit.loadout.mainHand).to.exist;
    });

    it("should filter inventory by slot type", async () => {
      inventoryManager.runStash.addItem({
        uid: "ITEM_001",
        defId: "ITEM_RUSTY_BLADE",
        isNew: true,
        quantity: 1,
      });
      inventoryManager.runStash.addItem({
        uid: "ITEM_002",
        defId: "ITEM_SCRAP_PLATE",
        isNew: false,
        quantity: 1,
      });

      element.unit = testUnit;
      element.inventoryManager = inventoryManager;
      element.gameMode = "DUNGEON";
      element.activeTab = "INVENTORY";
      element.selectedSlot = "WEAPON";
      await waitForUpdate();

      // Should only show weapons
      const itemCards = queryShadowAll(".item-card");
      expect(itemCards.length).to.equal(1);
    });
  });

  describe("CoA 4: fallback to legacy system", () => {
    it("should use legacy inventory array when inventoryManager is not provided", async () => {
      const legacyItem = new Item({
        id: "ITEM_LEGACY",
        name: "Legacy Item",
        type: "WEAPON",
        stats: { attack: 5 },
      });

      element.unit = testUnit;
      element.inventory = [legacyItem];
      element.selectedSlot = "WEAPON";
      element.activeTab = "INVENTORY";
      await waitForUpdate();

      const itemCards = queryShadowAll(".item-card");
      expect(itemCards.length).to.equal(1);
    });

    it("should use legacy equip logic when item has no uid", async () => {
      const legacyItem = new Item({
        id: "ITEM_LEGACY",
        name: "Legacy Item",
        type: "WEAPON",
        stats: { attack: 5 },
        canEquip: () => true,
      });

      element.unit = testUnit;
      element.inventory = [legacyItem];
      element.selectedSlot = "WEAPON";
      element.activeTab = "INVENTORY";
      await waitForUpdate();

      let equipEventFired = false;
      element.addEventListener("equip-item", () => {
        equipEventFired = true;
      });

      const itemCard = queryShadow(".item-card");
      itemCard.click();
      await waitForUpdate();

      expect(equipEventFired).to.be.true;
      // Should use legacy equipment system
      expect(testUnit.equipment.weapon).to.equal(legacyItem);
    });
  });
});

