package thb.jeanluc.adventure.io;

import org.junit.jupiter.api.Test;
import thb.jeanluc.adventure.io.text.Hud;
import thb.jeanluc.adventure.io.text.RoomView;
import thb.jeanluc.adventure.io.text.StyledText;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.io.StringReader;
import java.nio.charset.StandardCharsets;
import java.util.List;

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

class ConsoleIORenderTest {

    private ConsoleIO io(ByteArrayOutputStream sink) {
        PrintStream ps = new PrintStream(sink, true, StandardCharsets.UTF_8);
        return new ConsoleIO(new BufferedReader(new StringReader("")), ps,
                ConsoleIO.ColorMode.OFF, ConsoleIO.GlyphMode.UNICODE);
    }

    @Test
    void showRoom_drawsHeadingSectionsAndExits() {
        ByteArrayOutputStream sink = new ByteArrayOutputStream();
        io(sink).showRoom(new RoomView("Kitchen", "A cold kitchen.",
                List.of("Lamp"), List.of("Old Man"), List.of("north", "east")));
        String out = sink.toString(StandardCharsets.UTF_8);
        assertThat(out).contains("KITCHEN");
        assertThat(out).contains("A cold kitchen.");
        assertThat(out).contains("Lamp");
        assertThat(out).contains("Old Man");
        assertThat(out).contains("north").contains("east");
    }

    @Test
    void print_colorOff_emitsNoAnsiEscapes() {
        ByteArrayOutputStream sink = new ByteArrayOutputStream();
        io(sink).print(StyledText.builder().item("brass lamp").build());
        assertThat(sink.toString(StandardCharsets.UTF_8)).doesNotContain("[");
    }

    @Test
    void setHud_printsLocationGoldTurnAndLight() {
        ByteArrayOutputStream sink = new ByteArrayOutputStream();
        io(sink).setHud(new Hud("Kitchen", 0, 7, false));
        String out = sink.toString(StandardCharsets.UTF_8);
        assertThat(out).contains("Kitchen").contains("turn 7").contains("light: off");
    }

    @Test
    void readLine_returnsNullOnEof() {
        ByteArrayOutputStream sink = new ByteArrayOutputStream();
        PrintStream ps = new PrintStream(sink, true, StandardCharsets.UTF_8);
        ConsoleIO io = new ConsoleIO(new BufferedReader(new StringReader("")), ps,
                ConsoleIO.ColorMode.OFF, ConsoleIO.GlyphMode.UNICODE);
        assertThat(io.readLine()).isNull();
    }

    @Test
    void readLine_returnsEmptyStringForBlankLineThenNullAtEof() {
        ByteArrayOutputStream sink = new ByteArrayOutputStream();
        PrintStream ps = new PrintStream(sink, true, StandardCharsets.UTF_8);
        ConsoleIO io = new ConsoleIO(new BufferedReader(new StringReader("\n")), ps,
                ConsoleIO.ColorMode.OFF, ConsoleIO.GlyphMode.UNICODE);
        assertThat(io.readLine()).isEqualTo(""); // blank interactive line, re-prompt
        assertThat(io.readLine()).isNull();      // stream now exhausted → EOF
    }

    @Test
    void asciiGlyphMode_usesPlusDashFrame() {
        ByteArrayOutputStream sink = new ByteArrayOutputStream();
        PrintStream ps = new PrintStream(sink, true, StandardCharsets.UTF_8);
        new ConsoleIO(new BufferedReader(new StringReader("")), ps,
                ConsoleIO.ColorMode.OFF, ConsoleIO.GlyphMode.ASCII)
                .showRoom(new RoomView("Cell", "x", List.of(), List.of(), List.of("north")));
        String out = sink.toString(StandardCharsets.UTF_8);
        assertThat(out).contains("+").contains("-");
        assertThat(out).doesNotContain("─");
    }
}
