import contextlib
import io
import unittest

from abstra_internals.controllers.execution.snippet_output import TeeStream, as_logs


class BrokenStream(io.StringIO):
    def write(self, text: str) -> int:
        raise OSError("downstream is gone")

    def flush(self) -> None:
        raise OSError("downstream is gone")


class TeeStreamTest(unittest.TestCase):
    def test_captures_what_is_printed(self):
        downstream = io.StringIO()
        tee = TeeStream(downstream)

        with contextlib.redirect_stdout(tee):
            print("valor 1.234,56")

        self.assertIn("valor 1.234,56", tee.getvalue())

    def test_keeps_writing_downstream(self):
        downstream = io.StringIO()
        tee = TeeStream(downstream)

        with contextlib.redirect_stdout(tee):
            print("still visible in the pod logs")

        self.assertIn("still visible in the pod logs", downstream.getvalue())

    def test_captures_even_when_downstream_fails(self):
        tee = TeeStream(BrokenStream())

        with contextlib.redirect_stdout(tee):
            print("captured anyway")
        tee.flush()

        self.assertIn("captured anyway", tee.getvalue())

    def test_reports_the_full_length_written(self):
        tee = TeeStream(BrokenStream())

        self.assertEqual(tee.write("abcdef"), 6)


class AsLogsTest(unittest.TestCase):
    def test_omits_empty_streams(self):
        self.assertEqual(as_logs("", ""), [])

    def test_labels_each_stream(self):
        self.assertEqual(
            as_logs("out", "err"),
            [{"type": "stdout", "text": "out"}, {"type": "stderr", "text": "err"}],
        )

    def test_keeps_stderr_alone_when_nothing_was_printed(self):
        self.assertEqual(as_logs("", "boom"), [{"type": "stderr", "text": "boom"}])


if __name__ == "__main__":
    unittest.main()
