package thb.jeanluc.adventure.command;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import thb.jeanluc.adventure.command.impl.MenuCommand;
import thb.jeanluc.adventure.command.impl.SaveCommand;
import thb.jeanluc.adventure.game.Game;
import thb.jeanluc.adventure.game.GameContext;
import thb.jeanluc.adventure.game.GameSession;
import thb.jeanluc.adventure.io.TestIO;
import thb.jeanluc.adventure.loader.WorldLoader;
import thb.jeanluc.adventure.save.SaveService;

import java.nio.file.Path;
import java.util.List;

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

class SaveMenuCommandTest {

    private GameContext ctx(String slot) {
        WorldLoader.LoadResult r = new WorldLoader().load();
        return new GameContext(new GameSession(r.world(), r.player(), slot), new TestIO());
    }

    @Test
    void saveCommandWritesSlotAndReportsSuccess(@TempDir Path dir) {
        SaveService svc = new SaveService(dir);
        GameContext ctx = ctx("game-a");
        new SaveCommand(svc).execute(ctx, List.of());
        assertThat(svc.list()).extracting(s -> s.slotName()).containsExactly("game-a");
        assertThat(((TestIO) ctx.getIo()).allOutput()).contains("Game saved");
    }

    @Test
    void menuCommandSavesThenStopsLoop(@TempDir Path dir) {
        SaveService svc = new SaveService(dir);
        GameContext ctx = ctx("game-b");
        Game game = new Game(ctx, new CommandRegistry(), new CommandParser());
        MenuCommand menu = new MenuCommand(svc);
        menu.bind(game);
        menu.execute(ctx, List.of());
        assertThat(svc.list()).hasSize(1);
        // loop is stopped: run() must return without consuming queued input
        ((TestIO) ctx.getIo()).enqueue("look");
        game.run();
        assertThat(ctx.getIo().readLine()).isEqualTo("look"); // sentinel still unread
    }
}
