import { expect } from "@esm-bundle/chai";
import sinon from "sinon";
import { GameLoop } from "../../../src/core/GameLoop.js";
import { Explorer } from "../../../src/units/Explorer.js";
import { UnitManager } from "../../../src/managers/UnitManager.js";
import {
  createGameLoopSetup,
  cleanupGameLoop,
} from "./helpers.js";

// Mock Class Definition
const CLASS_VANGUARD = {
  id: "CLASS_VANGUARD",
  base_stats: { health: 100, attack: 10, speed: 5 },
  growth_rates: { health: 10, attack: 1 },
};

describe("Core: GameLoop - Explorer Progression", function () {
  this.timeout(30000);

  let gameLoop;
  let container;

  beforeEach(async () => {
    const setup = createGameLoopSetup();
    gameLoop = setup.gameLoop;
    container = setup.container;
    await gameLoop.init(container);
    
    // Ensure unitManager is initialized (it's created during init)
    // If it's not, create a minimal one for testing
    if (!gameLoop.unitManager) {
      gameLoop.unitManager = new UnitManager({});
    }
  });

  afterEach(() => {
    cleanupGameLoop(gameLoop, container);
  });

  it("CoA 1: _saveExplorerProgression should save classMastery to roster", () => {
    // Setup: Create a mock gameStateManager with roster
    const mockRosterUnit = {
      id: "UNIT_1",
      classId: "CLASS_VANGUARD",
      name: "Test Explorer",
      status: "READY",
    };

    const mockRosterManager = {
      roster: [mockRosterUnit],
    };

    const mockGameStateManager = {
      rosterManager: mockRosterManager,
      _saveRoster: sinon.spy(),
    };

    gameLoop.gameStateManager = mockGameStateManager;

    // Create an Explorer unit with progression
    const explorer = new Explorer("UNIT_1", "Test Explorer", "CLASS_VANGUARD", CLASS_VANGUARD);
    explorer.rosterId = "UNIT_1";
    explorer.classMastery.CLASS_VANGUARD.level = 5;
    explorer.classMastery.CLASS_VANGUARD.xp = 250;
    explorer.classMastery.CLASS_VANGUARD.skillPoints = 3;
    explorer.classMastery.CLASS_VANGUARD.unlockedNodes = ["ROOT", "NODE_1"];
    explorer.activeClassId = "CLASS_VANGUARD";

    // Add to unit manager
    gameLoop.unitManager.activeUnits.set(explorer.id, explorer);
    explorer.team = "PLAYER";

    // Call the save method
    gameLoop._saveExplorerProgression();

    // Verify progression was saved to roster
    expect(mockRosterUnit.classMastery).to.exist;
    expect(mockRosterUnit.classMastery.CLASS_VANGUARD.level).to.equal(5);
    expect(mockRosterUnit.classMastery.CLASS_VANGUARD.xp).to.equal(250);
    expect(mockRosterUnit.classMastery.CLASS_VANGUARD.skillPoints).to.equal(3);
    expect(mockRosterUnit.classMastery.CLASS_VANGUARD.unlockedNodes).to.include("ROOT");
    expect(mockRosterUnit.classMastery.CLASS_VANGUARD.unlockedNodes).to.include("NODE_1");
    expect(mockRosterUnit.activeClassId).to.equal("CLASS_VANGUARD");

    // Verify roster was saved
    expect(mockGameStateManager._saveRoster.called).to.be.true;
  });

  it("CoA 2: _saveExplorerProgression should handle multiple Explorers", () => {
    const mockRosterUnit1 = {
      id: "UNIT_1",
      classId: "CLASS_VANGUARD",
      name: "Explorer 1",
      status: "READY",
    };

    const mockRosterUnit2 = {
      id: "UNIT_2",
      classId: "CLASS_TINKER",
      name: "Explorer 2",
      status: "READY",
    };

    const mockRosterManager = {
      roster: [mockRosterUnit1, mockRosterUnit2],
    };

    const mockGameStateManager = {
      rosterManager: mockRosterManager,
      _saveRoster: sinon.spy(),
    };

    gameLoop.gameStateManager = mockGameStateManager;

    // Create two Explorers with different progression
    const explorer1 = new Explorer("UNIT_1", "Explorer 1", "CLASS_VANGUARD", CLASS_VANGUARD);
    explorer1.rosterId = "UNIT_1";
    explorer1.classMastery.CLASS_VANGUARD.level = 3;
    explorer1.team = "PLAYER";
    gameLoop.unitManager.activeUnits.set(explorer1.id, explorer1);

    const explorer2 = new Explorer("UNIT_2", "Explorer 2", "CLASS_TINKER", {
      id: "CLASS_TINKER",
      base_stats: { health: 80, attack: 8 },
      growth_rates: { health: 5, attack: 2 },
    });
    explorer2.rosterId = "UNIT_2";
    explorer2.classMastery.CLASS_TINKER.level = 7;
    explorer2.team = "PLAYER";
    gameLoop.unitManager.activeUnits.set(explorer2.id, explorer2);

    gameLoop._saveExplorerProgression();

    // Verify both were saved
    expect(mockRosterUnit1.classMastery.CLASS_VANGUARD.level).to.equal(3);
    expect(mockRosterUnit2.classMastery.CLASS_TINKER.level).to.equal(7);
  });

  it("CoA 3: _saveExplorerProgression should not save if unit not in roster", () => {
    const mockRosterManager = {
      roster: [],
    };

    const mockGameStateManager = {
      rosterManager: mockRosterManager,
      _saveRoster: sinon.spy(),
    };

    gameLoop.gameStateManager = mockGameStateManager;

    // Create an Explorer that's not in roster
    const explorer = new Explorer("UNIT_UNKNOWN", "Unknown", "CLASS_VANGUARD", CLASS_VANGUARD);
    explorer.rosterId = "UNIT_UNKNOWN";
    explorer.classMastery.CLASS_VANGUARD.level = 5;
    explorer.team = "PLAYER";
    gameLoop.unitManager.activeUnits.set(explorer.id, explorer);

    gameLoop._saveExplorerProgression();

    // Should not crash, but roster should remain empty
    expect(mockRosterManager.roster).to.be.empty;
    // Should still call save (in case other units were updated)
    expect(mockGameStateManager._saveRoster.called).to.be.true;
  });

  it("CoA 4: _handleMissionVictory should save progression", () => {
    const mockRosterUnit = {
      id: "UNIT_1",
      classId: "CLASS_VANGUARD",
      name: "Test Explorer",
      status: "READY",
    };

    const mockRosterManager = {
      roster: [mockRosterUnit],
    };

    const mockGameStateManager = {
      rosterManager: mockRosterManager,
      _saveRoster: sinon.spy(),
      transitionTo: sinon.spy(),
    };

    gameLoop.gameStateManager = mockGameStateManager;
    gameLoop.isPaused = false;
    gameLoop.stop = sinon.spy();

    // Create Explorer with progression
    const explorer = new Explorer("UNIT_1", "Test Explorer", "CLASS_VANGUARD", CLASS_VANGUARD);
    explorer.rosterId = "UNIT_1";
    explorer.classMastery.CLASS_VANGUARD.level = 4;
    explorer.team = "PLAYER";
    gameLoop.unitManager.activeUnits.set(explorer.id, explorer);

    // Call victory handler
    gameLoop._handleMissionVictory({ missionId: "TEST_MISSION" });

    // Verify progression was saved
    expect(mockRosterUnit.classMastery.CLASS_VANGUARD.level).to.equal(4);
    expect(mockGameStateManager._saveRoster.called).to.be.true;
  });
});

