package thb.jeanluc.adventure.game;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import thb.jeanluc.adventure.command.CommandParser;
import thb.jeanluc.adventure.command.CommandRegistry;
import thb.jeanluc.adventure.command.impl.GoCommand;
import thb.jeanluc.adventure.command.impl.LookCommand;
import thb.jeanluc.adventure.command.impl.MenuCommand;
import thb.jeanluc.adventure.io.TestIO;
import thb.jeanluc.adventure.model.Direction;
import thb.jeanluc.adventure.model.Player;
import thb.jeanluc.adventure.model.Room;
import thb.jeanluc.adventure.model.World;
import thb.jeanluc.adventure.save.SaveService;

import java.nio.file.Path;
import java.util.LinkedHashMap;
import java.util.Map;

import static org.assertj.core.api.Assertions.assertThat;

class GameTest {

    @TempDir
    Path savesDir;

    @Test
    void run_dispatchesCommands_andQuitsCleanly() {
        Room kitchen = new Room("kitchen", "Kitchen", "kd");
        Room hallway = new Room("hallway", "Hallway", "hd");
        kitchen.addExit(Direction.NORTH, hallway);
        Player player = new Player(kitchen, 0);
        TestIO io = new TestIO()
                .enqueue("go north")
                .enqueue("quit");
        Map<String, Room> rooms = new LinkedHashMap<>();
        rooms.put("kitchen", kitchen);
        rooms.put("hallway", hallway);
        GameContext ctx = new GameContext(new World(rooms, Map.of(), Map.of(), "t", "w"), player, io);

        CommandRegistry registry = new CommandRegistry();
        registry.register(new GoCommand(), "go");
        registry.register(new LookCommand(), "look");
        MenuCommand quit = new MenuCommand(new SaveService(savesDir));
        registry.register(quit, "quit");

        Game game = new Game(ctx, registry, new CommandParser());
        quit.bind(game);
        game.run();

        assertThat(player.getCurrentRoom()).isEqualTo(hallway);
        assertThat(io.allOutput()).contains("Returning to the main menu");
    }

    @Test
    void run_unknownVerb_writesHint() {
        Room r = new Room("r", "R", "d");
        Player player = new Player(r, 0);
        TestIO io = new TestIO().enqueue("dance").enqueue("quit");
        GameContext ctx = new GameContext(new World(Map.of("r", r), Map.of(), Map.of(), "t", "w"), player, io);

        CommandRegistry registry = new CommandRegistry();
        MenuCommand quit = new MenuCommand(new SaveService(savesDir));
        registry.register(quit, "quit");
        Game game = new Game(ctx, registry, new CommandParser());
        quit.bind(game);
        game.run();

        assertThat(io.allOutput()).contains("don't understand 'dance'");
    }
}
