import inspect
import os
import random
import sys
import retro
import tetris
from retro.agent import ArrowKeyAgent



# Expose Game name expected by create_game helper
game = tetris.Tetris()


# --- Factory helpers and small harness ---

def create_game():
    """Create a Game instance with minimal sensible defaults."""
    try:
        return Game()
    except TypeError:
        try:
            sig = inspect.signature(Game)
            kwargs = {}
            if 'agents' in sig.parameters:
                kwargs['agents'] = []
            if 'state' in sig.parameters:
                kwargs['state'] = {}
            return Game(**kwargs)
        except Exception:
            for args in (([], {}), ([], None), ([],), (None,)):
                try:
                    return Game(*args)
                except Exception:
                    continue
            raise


def create_agent(game=None):
    try:
        return ArrowKeyAgent(game)
    except TypeError:
        return ArrowKeyAgent()


def draw_screen(game: Game):
    # simple text render
    game.clear()
    s = game.draw_board()
    game.refresh()
    # store/return the string for tests
    return s


def main():
    argv = sys.argv[1:]
    if len(argv) >= 1 and argv[0] == 'play':
        # Try to run a terminal player. Use curses if available.
        try:
            play_in_terminal(create_game())
        except Exception as e:
            print('Terminal play failed:', e)
            print('Run without args to run smoke tests instead.')
        return

    game = create_game()
    agent = create_agent(game)

    while not game.is_over():
        action = agent.get_action()
        game.step(action)
        draw_screen(game)

    print('Game Over! Score:', game.get_score())

def play_in_terminal(game):
    """Simple curses-based player loop.

    Controls:
    - Left/Right arrows or 'a'/'d' to move
    - Up arrow or 'w' to rotate
    - Down arrow or 's' to soft drop
    - Space for hard drop
    - 'q' to quit
    """

    keymap = {
        # map keys to the Testris.action integer codes:
        # 0 noop, 1 left, 2 right, 3 rotate, 4 soft drop
        curses.KEY_LEFT: 1,
        curses.KEY_RIGHT: 2,
        curses.KEY_UP: 3,
        curses.KEY_DOWN: 4,
        ord('a'): 1,
        ord('d'): 2,
        ord('w'): 3,
        ord('s'): 4,
        # space will perform a hard drop (special handling)
        ord(' '): 'hard_drop',
        ord('q'): 'quit',
    }







# --- Simple smoke tests ---

def test_game_initialization():
    g = create_game()
    assert g is not None
    assert g.get_score() == 0
    assert not g.is_over()


def test_game_step():
    g = create_game()
    score0 = g.get_score()
    g.step(0)
    assert g.get_score() >= score0


def test_draw_board_returns_str():
    g = create_game()
    s = g.draw_board()
    assert isinstance(s, str)


def test_game_over_sequence():
    g = create_game()
    # run a few steps to ensure no immediate crash
    for _ in range(50):
        if g.is_over():
            break
        g.step(0)
    assert g.get_score() >= 0


if __name__ == '__main__':
    main()
