package thb.jeanluc.adventure.command.impl;

import org.junit.jupiter.api.Test;
import thb.jeanluc.adventure.game.GameContext;
import thb.jeanluc.adventure.io.TestIO;
import thb.jeanluc.adventure.model.Combination;
import thb.jeanluc.adventure.model.Player;
import thb.jeanluc.adventure.model.Room;
import thb.jeanluc.adventure.model.World;
import thb.jeanluc.adventure.model.item.Item;
import thb.jeanluc.adventure.model.item.PlainItem;
import thb.jeanluc.adventure.model.item.SwitchableItem;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

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

class UseCommandComboTest {

    private GameContext ctx() {
        Map<String, Item> items = new LinkedHashMap<>();
        items.put("matches", PlainItem.builder().id("matches").name("Matches").description("d").light(false).build());
        items.put("torch", PlainItem.builder().id("torch").name("Torch").description("d").light(false).build());
        items.put("lit_torch", PlainItem.builder().id("lit_torch").name("Lit Torch").description("d").light(true).build());
        SwitchableItem lamp = SwitchableItem.builder()
                .id("lamp").name("Lamp").description("d").light(true)
                .onText("The lamp glows.").offText("off").state(false).effects(List.of()).build();
        items.put("lamp", lamp);
        Combination recipe = new Combination("matches", "torch", List.of(),
                List.of("matches", "torch"), "lit_torch", List.of(), "You light the torch.", null);
        Room start = new Room("start", "Start", "d");
        World w = new World(Map.of("start", start), items, Map.of(), "t", "w",
                Map.of(), List.of(), Map.of(recipe.key(), recipe));
        GameContext ctx = new GameContext(w, new Player(start, 0), new TestIO());
        ctx.getPlayer().addItem(items.get("matches"));
        ctx.getPlayer().addItem(items.get("torch"));
        ctx.getPlayer().addItem(lamp);
        return ctx;
    }

    @Test
    void emptyArgsAsksWhat() {
        GameContext ctx = ctx();
        new UseCommand().execute(ctx, List.of());
        assertThat(((TestIO) ctx.getIo()).allOutput()).contains("Use what?");
    }

    @Test
    void twoArgsRoutesToCombination() {
        GameContext ctx = ctx();
        new UseCommand().execute(ctx, List.of("matches", "torch"));
        assertThat(ctx.getPlayer().hasItem("lit_torch")).isTrue();
        assertThat(((TestIO) ctx.getIo()).allOutput()).contains("light the torch");
    }

    @Test
    void oneArgUsesItemDirectly() {
        GameContext ctx = ctx();
        new UseCommand().execute(ctx, List.of("lamp"));
        assertThat(((SwitchableItem) ctx.getWorld().getItems().get("lamp")).isOn()).isTrue();
        assertThat(((TestIO) ctx.getIo()).allOutput()).contains("lamp glows");
    }
}
