"""Tests for display output, especially cross-platform encoding."""

import io
import sys

from rich.console import Console

from gjalla_precommit.display.output import (
    BRIDGE_ART,
    _ensure_utf8,
    make_console,
    section_display,
)


class TestEnsureUtf8:
    """Tests for _ensure_utf8 encoding reconfiguration."""

    def test_noop_when_already_utf8(self):
        """Does not reconfigure a stream that is already UTF-8."""
        stream = io.TextIOWrapper(io.BytesIO(), encoding="utf-8")
        _ensure_utf8(stream)
        assert stream.encoding == "utf-8"

    def test_reconfigures_non_utf8_stream(self):
        """Reconfigures a cp1252 stream to UTF-8."""
        stream = io.TextIOWrapper(io.BytesIO(), encoding="cp1252")
        _ensure_utf8(stream)
        assert stream.encoding == "utf-8"

    def test_skips_object_without_reconfigure(self):
        """Gracefully skips objects that lack reconfigure (e.g. pytest capture)."""
        class FakeStream:
            encoding = "cp1252"
        _ensure_utf8(FakeStream())  # should not raise

    def test_skips_none_encoding(self):
        """Handles streams with encoding=None (e.g. binary mode)."""
        class FakeStream:
            encoding = None
            def reconfigure(self, **kw): pass
        _ensure_utf8(FakeStream())  # should not raise


class TestMakeConsole:
    """Tests for make_console factory."""

    def test_returns_console(self):
        c = make_console()
        assert isinstance(c, Console)

    def test_stderr_flag(self):
        c = make_console(stderr=True)
        assert isinstance(c, Console)


class TestBridgeArtEncoding:
    """Verify bridge art renders without encoding errors on all platforms."""

    def test_bridge_art_encodes_to_utf8(self):
        """All bridge art characters must be valid UTF-8."""
        from rich.text import Text
        rendered = Text.from_markup(BRIDGE_ART)
        plain = rendered.plain
        plain.encode("utf-8")  # must not raise

    def test_bridge_art_fails_cp1252(self):
        """Bridge art contains characters outside cp1252 — confirms the
        encoding fix is necessary."""
        from rich.text import Text
        rendered = Text.from_markup(BRIDGE_ART)
        plain = rendered.plain
        try:
            plain.encode("cp1252")
            # If it doesn't raise, the art only uses cp1252-safe chars
            # and the encoding fix is technically unnecessary (but still harmless)
        except UnicodeEncodeError:
            pass  # expected — confirms bridge art needs UTF-8

    def test_section_display_renders_to_string(self):
        """section_display writes to a console without crashing."""
        buf = io.StringIO()
        c = Console(file=buf, width=80)
        # Temporarily swap module-level console
        import gjalla_precommit.display.output as out
        original = out.console
        out.console = c
        try:
            section_display("Test Title", "Some content here.", color="green")
            output = buf.getvalue()
            assert "Test Title" in output
            assert "Some content" in output
        finally:
            out.console = original

    def test_section_display_strips_h1_only(self):
        """Only h1 headings are stripped, not h2+."""
        buf = io.StringIO()
        c = Console(file=buf, width=80)
        import gjalla_precommit.display.output as out
        original = out.console
        out.console = c
        try:
            section_display("Rules", "## Subsection\n\nBody text.")
            output = buf.getvalue()
            assert "Subsection" in output
        finally:
            out.console = original

    def test_section_display_plain_text_no_markup_injection(self):
        """Plain text mode must not interpret Rich markup in content."""
        buf = io.StringIO()
        c = Console(file=buf, width=80)
        import gjalla_precommit.display.output as out
        original = out.console
        out.console = c
        try:
            section_display(
                "State",
                '{"key": "[bold]not bold[/bold]"}',
                is_markdown=False,
            )
            output = buf.getvalue()
            assert "[bold]not bold[/bold]" in output
        finally:
            out.console = original
