import { expect } from "@esm-bundle/chai";
import sinon from "sinon";
import {
  gameStateManager,
  GameStateManager,
} from "../../../src/core/GameStateManager.js";

describe("Core: GameStateManager - Hub Integration", () => {
  let mockPersistence;
  let mockGameLoop;

  beforeEach(() => {
    gameStateManager.reset();

    mockPersistence = {
      init: sinon.stub().resolves(),
      saveRun: sinon.stub().resolves(),
      loadRun: sinon.stub().resolves(null),
      loadRoster: sinon.stub().resolves(null),
      saveRoster: sinon.stub().resolves(),
      loadCampaign: sinon.stub().resolves(null),
      saveCampaign: sinon.stub().resolves(),
      loadMarketState: sinon.stub().resolves(null),
      saveMarketState: sinon.stub().resolves(),
      loadHubStash: sinon.stub().resolves(null),
      saveHubStash: sinon.stub().resolves(),
      loadUnlocks: sinon.stub().resolves([]),
      saveUnlocks: sinon.stub().resolves(),
    };
    gameStateManager.persistence = mockPersistence;

    mockGameLoop = {
      init: sinon.spy(),
      startLevel: sinon.stub().resolves(),
      stop: sinon.spy(),
    };

    gameStateManager.missionManager = {
      setupActiveMission: sinon.stub(),
      getActiveMission: sinon.stub().returns({
        id: "MISSION_TUTORIAL_01",
        config: { title: "Test Mission" },
        biome: {
          generator_config: {
            seed_type: "RANDOM",
            seed: 12345,
          },
        },
        objectives: [],
      }),
      playIntro: sinon.stub().resolves(),
      missionRegistry: new Map(),
      load: sinon.stub(),
      save: sinon.stub().returns({ completedMissions: [] }),
      completedMissions: new Set(),
    };
  });

  describe("continueGame - Hub vs Main Menu Logic", () => {
    it("should go to Hub when there's campaign progress but no active run", async () => {
      // Setup: roster exists (campaign progress)
      gameStateManager.rosterManager.roster = [
        { id: "u1", name: "Test Unit", status: "READY" },
      ];
      mockPersistence.loadRun.resolves(null); // No active run

      await gameStateManager.init();
      const transitionSpy = sinon.spy(gameStateManager, "transitionTo");

      await gameStateManager.continueGame();

      expect(mockPersistence.loadRun.called).to.be.true;
      expect(transitionSpy.calledWith(GameStateManager.STATES.MAIN_MENU)).to.be.true;
      // Hub should show because roster exists
    });

    it("should resume active run when save exists", async () => {
      const savedRun = {
        id: "RUN_123",
        missionId: "MISSION_TUTORIAL_01",
        seed: 12345,
        depth: 1,
        squad: [],
      };
      mockPersistence.loadRun.resolves(savedRun);
      gameStateManager.setGameLoop(mockGameLoop);

      await gameStateManager.init();
      await gameStateManager.continueGame();

      expect(mockPersistence.loadRun.called).to.be.true;
      expect(gameStateManager.activeRunData).to.deep.equal(savedRun);
      expect(mockGameLoop.startLevel.called).to.be.true;
      // Should transition to DEPLOYMENT, not MAIN_MENU
    });

    it("should go to Hub when completed missions exist but no active run", async () => {
      gameStateManager.missionManager.completedMissions.add("MISSION_TUTORIAL_01");
      mockPersistence.loadRun.resolves(null);

      await gameStateManager.init();
      const transitionSpy = sinon.spy(gameStateManager, "transitionTo");

      await gameStateManager.continueGame();

      expect(transitionSpy.calledWith(GameStateManager.STATES.MAIN_MENU)).to.be.true;
      // Hub should show because completed missions exist
    });

    it("should stay on main menu when no campaign progress and no active run", async () => {
      // No roster, no completed missions, no active run
      gameStateManager.rosterManager.roster = [];
      gameStateManager.missionManager.completedMissions.clear();
      mockPersistence.loadRun.resolves(null);

      await gameStateManager.init();
      const transitionSpy = sinon.spy(gameStateManager, "transitionTo");

      await gameStateManager.continueGame();

      // Should not transition (stays on current state)
      // Main menu should remain visible
      expect(transitionSpy.called).to.be.false;
    });

    it("should prioritize active run over campaign progress", async () => {
      // Both active run and campaign progress exist
      const savedRun = {
        id: "RUN_123",
        missionId: "MISSION_TUTORIAL_01",
        seed: 12345,
        depth: 1,
        squad: [],
      };
      mockPersistence.loadRun.resolves(savedRun);
      gameStateManager.rosterManager.roster = [
        { id: "u1", name: "Test Unit", status: "READY" },
      ];
      gameStateManager.setGameLoop(mockGameLoop);

      await gameStateManager.init();
      await gameStateManager.continueGame();

      // Should resume run, not go to hub
      expect(mockGameLoop.startLevel.called).to.be.true;
      expect(gameStateManager.activeRunData).to.deep.equal(savedRun);
    });
  });

  describe("State Transitions - Hub Visibility", () => {
    it("should transition to MAIN_MENU after mission completion", async () => {
      // This simulates what happens after mission victory
      await gameStateManager.init();
      gameStateManager.rosterManager.roster = [
        { id: "u1", name: "Test Unit", status: "READY" },
      ];

      const transitionSpy = sinon.spy(gameStateManager, "transitionTo");
      await gameStateManager.transitionTo(GameStateManager.STATES.MAIN_MENU);

      expect(transitionSpy.calledWith(GameStateManager.STATES.MAIN_MENU)).to.be.true;
      // Hub should be shown because roster exists
    });
  });
});

