import { describe, it, expect, vi, beforeEach } from 'vitest';
import { GameScene } from '../GameScene';
import * as simulation from '../../engine/simulation/simulation';
import * as generator from '../../engine/world/generator';

// Mock Phaser
vi.mock('phaser', () => {
  const mockEventEmitter = {
    on: vi.fn(),
    emit: vi.fn(),
    off: vi.fn(),
  };

  return {
    default: {
      Scene: class {
        events = mockEventEmitter;
        input = {
          keyboard: {
            createCursorKeys: vi.fn(() => ({})),
            on: vi.fn(),
          },
          on: vi.fn(),
        };
        cameras = {
          main: {
            setZoom: vi.fn(),
            setBounds: vi.fn(),
            centerOn: vi.fn(),
          },
        };
        scene = {
          launch: vi.fn(),
          get: vi.fn(),
        };
        add = {
           graphics: vi.fn(() => ({})),
           text: vi.fn(() => ({})),
           rectangle: vi.fn(() => ({})),
           container: vi.fn(() => ({})),
        };
        load = {
          spritesheet: vi.fn(),
        };
        anims = {
          create: vi.fn(),
          exists: vi.fn(() => true),
          generateFrameNumbers: vi.fn(),
        };
      },
      Input: {
        Keyboard: {
          JustDown: vi.fn(),
        },
      },
    },
  };
});

// Mock other modules
vi.mock('../../rendering/DungeonRenderer', () => ({
  DungeonRenderer: vi.fn().mockImplementation(function() {
    return {
      initializeFloor: vi.fn(),

      computeFov: vi.fn(),
      render: vi.fn(),
      showDamage: vi.fn(),
      spawnCorpse: vi.fn(),
      showWait: vi.fn(),
      isMinimapVisible: vi.fn(() => false),
    };
  }),
}));

vi.mock('../../engine/simulation/simulation', () => ({
  applyAction: vi.fn(),
  stepUntilPlayerTurn: vi.fn(),
}));

vi.mock('../../engine/world/generator', () => ({
  generateWorld: vi.fn(),

}));

vi.mock('../../engine/world/world-logic', () => ({
  inBounds: vi.fn(() => true),
  isBlocked: vi.fn(() => false),
  isPlayerOnExit: vi.fn(() => false),
  idx: vi.fn((w, x, y) => y * w.width + x),
}));

describe('GameScene', () => {
  let scene: GameScene;
  let mockWorld: any;
  let mockUI: any;

  beforeEach(() => {
    vi.clearAllMocks();
    
    // Setup mock UI
    mockUI = {
      showDeathScreen: vi.fn(),
    };

    // Initialize Scene
    scene = new GameScene();
    
    // Mock the Phaser scene system to return our mock UI
    (scene as any).scene = {
      launch: vi.fn(),
      get: vi.fn((key) => {
        if (key === 'GameUI') return mockUI;
        return null;
      }),
    };

    // Mock initial world state
    mockWorld = {
      width: 10,
      height: 10,
      tiles: new Array(100).fill(0),
      actors: new Map(),
      exit: { x: 9, y: 9 },
    };

    const mockPlayer = {
      id: 1,
      isPlayer: true,
      pos: { x: 1, y: 1 },
      speed: 100,
      energy: 0,
      stats: { hp: 10, maxHp: 10, attack: 5, defense: 2 },
      inventory: { gold: 0, items: [] },
    };
    mockWorld.actors.set(1, mockPlayer);

    (generator.generateWorld as any).mockReturnValue({

      world: mockWorld,
      playerId: 1,
    });

    (simulation.stepUntilPlayerTurn as any).mockReturnValue({
      awaitingPlayerId: 1,
      events: [],
    });

    // Run create to initialize some things
    scene.create();
  });

  it('should trigger death screen when player is killed', () => {
    // 1. Mock simulation so that after action, player is gone from world
    (simulation.applyAction as any).mockImplementation((world: any) => {
      // simulate player being killed
      world.actors.delete(1);
      return [{ type: 'killed', targetId: 1, victimType: 'player', x: 1, y: 1 }];
    });

    (simulation.stepUntilPlayerTurn as any).mockReturnValue({
      awaitingPlayerId: null,
      events: [],
    });

    // 2. Commit an action
    // We need to access private method or trigger it via public interface
    // commitPlayerAction is private, let's cast to any to call it
    (scene as any).commitPlayerAction({ type: 'wait' });

    // 3. Verify showDeathScreen was called on the mock UI
    expect(mockUI.showDeathScreen).toHaveBeenCalled();
    
    // Verify it was called with some stats
    const callArgs = mockUI.showDeathScreen.mock.calls[0][0];
    expect(callArgs).toHaveProperty('floor');

    expect(callArgs).toHaveProperty('gold');
    expect(callArgs).toHaveProperty('stats');
  });
});
