import sinon from "sinon";
import { GameLoop } from "../../../src/core/GameLoop.js";

/**
 * Creates a basic GameLoop setup for tests.
 * @returns {{ gameLoop: GameLoop; container: HTMLElement }}
 */
export function createGameLoopSetup() {
  const container = document.createElement("div");
  document.body.appendChild(container);
  const gameLoop = new GameLoop();
  return { gameLoop, container };
}

/**
 * Cleans up GameLoop after tests.
 * @param {GameLoop} gameLoop
 * @param {HTMLElement} container
 */
export function cleanupGameLoop(gameLoop, container) {
  gameLoop.stop();
  if (container.parentNode) {
    container.parentNode.removeChild(container);
  }

  // Cleanup Three.js resources if possible to avoid context loss limits
  if (gameLoop.renderer) {
    gameLoop.renderer.dispose();
    gameLoop.renderer.forceContextLoss();
  }
}

/**
 * Creates a mock game state manager for deployment phase.
 * @returns {Object}
 */
export function createMockGameStateManagerForDeployment() {
  return {
    currentState: "STATE_DEPLOYMENT",
    transitionTo: sinon.stub(),
    setCombatState: sinon.stub(),
    getCombatState: sinon.stub().returns(null),
    rosterManager: {
      roster: [],
    },
  };
}

/**
 * Creates a mock game state manager for combat phase.
 * @returns {Object}
 */
export function createMockGameStateManagerForCombat() {
  return {
    currentState: "STATE_COMBAT",
    transitionTo: sinon.stub(),
    setCombatState: sinon.stub(),
    getCombatState: sinon.stub(),
    rosterManager: {
      roster: [],
    },
  };
}

/**
 * Creates a mock mission manager with enemy spawns.
 * @param {Array} enemySpawns
 * @returns {Object}
 */
export function createMockMissionManager(enemySpawns = []) {
  const mockMissionDef = {
    id: "MISSION_TEST",
    config: { title: "Test Mission" },
    enemy_spawns: enemySpawns,
    objectives: { primary: [] },
  };

  return {
    getActiveMission: sinon.stub().returns(mockMissionDef),
  };
}

/**
 * Creates basic run data for tests.
 * @param {Object} overrides
 * @returns {Object}
 */
export function createRunData(overrides = {}) {
  return {
    seed: 12345,
    depth: 1,
    squad: [],
    ...overrides,
  };
}

/**
 * Sets up combat test units.
 * @param {GameLoop} gameLoop
 * @returns {{ playerUnit: Object; enemyUnit: Object }}
 */
export function setupCombatUnits(gameLoop) {
  const playerUnit = gameLoop.unitManager.createUnit("CLASS_VANGUARD", "PLAYER");
  playerUnit.baseStats.movement = 4;
  playerUnit.baseStats.speed = 10;
  playerUnit.currentAP = 10;
  playerUnit.chargeMeter = 100;
  playerUnit.position = { x: 5, y: 1, z: 5 };
  gameLoop.grid.placeUnit(playerUnit, playerUnit.position);
  gameLoop.createUnitMesh(playerUnit, playerUnit.position);

  const enemyUnit = gameLoop.unitManager.createUnit("ENEMY_DEFAULT", "ENEMY");
  enemyUnit.baseStats.speed = 8;
  enemyUnit.chargeMeter = 80;
  enemyUnit.position = { x: 15, y: 1, z: 15 };
  gameLoop.grid.placeUnit(enemyUnit, enemyUnit.position);
  gameLoop.createUnitMesh(enemyUnit, enemyUnit.position);

  return { playerUnit, enemyUnit };
}

/**
 * Cleans up turn system state.
 * @param {GameLoop} gameLoop
 */
export function cleanupTurnSystem(gameLoop) {
  if (gameLoop.turnSystem) {
    try {
      // First, try to end combat immediately to stop any ongoing turn advancement
      if (
        gameLoop.turnSystem.phase !== "INIT" &&
        gameLoop.turnSystem.phase !== "COMBAT_END"
      ) {
        // End combat first to stop any loops
        gameLoop.turnSystem.endCombat();
      }
      
      // Then reset the turn system
      if (typeof gameLoop.turnSystem.reset === "function") {
        gameLoop.turnSystem.reset();
      } else {
        // Fallback: manually reset state
        gameLoop.turnSystem.globalTick = 0;
        gameLoop.turnSystem.activeUnitId = null;
        gameLoop.turnSystem.phase = "INIT";
        gameLoop.turnSystem.round = 1;
        gameLoop.turnSystem.turnQueue = [];
      }
    } catch (e) {
      // Ignore errors during cleanup
      console.warn("Error during turn system cleanup:", e);
    }
  }
}

