"""Real child output must drain even when no interactive console is consuming it."""

import logging
import subprocess
import sys

import pytest

from hermes_cli.desktop_console import desktop_console_output, desktop_launch_notice


@pytest.mark.platforms("windows")
def test_packaged_console_output_drains_both_streams(caplog, monkeypatch):
    caplog.set_level(logging.INFO, logger="hermes_cli.desktop")

    def blocked_console(*args, **kwargs):
        raise AssertionError("packaged startup attempted a synchronous console write")

    monkeypatch.setattr("builtins.print", blocked_console)
    desktop_launch_notice("Starting Hermes")
    with desktop_console_output(source_mode=False) as streams:
        result = subprocess.run(
            [sys.executable, "-c", "import sys; sys.stdout.write('x'*131072); "
             "sys.stdout.flush(); sys.stderr.write('diagnostic\\n'); sys.exit(7)"],
            timeout=15, check=False, **streams,
        )
    assert result.returncode == 7
    messages = [record.getMessage() for record in caplog.records]
    assert sum(message.count("x") for message in messages) == 131072
    assert any("diagnostic" in message for message in messages)


@pytest.mark.platforms("windows")
@pytest.mark.parametrize("level", [logging.WARNING, logging.ERROR])
def test_stderr_survives_logging_threshold(caplog, level):
    caplog.set_level(level, logger="hermes_cli.desktop")
    with desktop_console_output(source_mode=False) as streams:
        result = subprocess.run(
            [sys.executable, "-c", "import sys; print('ordinary-output'); "
             "sys.stderr.write('fatal-diagnostic\\n'); sys.exit(7)"],
            timeout=15, check=False, **streams,
        )
    assert result.returncode == 7
    messages = [record.getMessage() for record in caplog.records]
    assert any("fatal-diagnostic" in message for message in messages)
    assert not any("ordinary-output" in message for message in messages)


@pytest.mark.platforms("windows")
@pytest.mark.parametrize("stream", ["stdout", "stderr"])
def test_complete_records_reach_redacted_logs(tmp_path, monkeypatch, caplog, stream):
    import hermes_logging

    monkeypatch.setenv("HERMES_HOME", str(tmp_path))
    hermes_logging._reset_queued_handlers()
    caplog.set_level(logging.INFO)
    caplog.set_level(logging.INFO, logger="hermes_cli.desktop")
    secret = "synthetic-boundary-credential"
    payload = (
        b" " * (8192 - len(b"API_KEY=")) + b"API_KEY=" + secret.encode() + b"\n"
        + b"u" * 8191 + "\u20ac\n".encode()
        + b"oversized-start API_KEY=" + secret.encode() + b"z" * 262144
        + b"oversized-end\nrecovered\ntail " + "\u20ac".encode()
    )
    payload_path = tmp_path / "child-output.bin"
    payload_path.write_bytes(payload)
    try:
        log_dir = hermes_logging.setup_logging(hermes_home=tmp_path, log_level="INFO", mode="gui")
        with desktop_console_output(source_mode=False) as streams:
            result = subprocess.run(
                [sys.executable, "-c", "import pathlib, sys; "
                 "data = pathlib.Path(sys.argv[1]).read_bytes(); "
                 "out = getattr(sys, sys.argv[2]).buffer; "
                 "[(out.write(data[i:i+997]), out.flush()) for i in range(0, len(data), 997)]",
                 str(payload_path), stream],
                timeout=15, check=False, **streams,
            )
        assert result.returncode == 0
        hermes_logging.flush_log_queue()
        text = (log_dir / "agent.log").read_text(encoding="utf-8")
        assert secret not in text
        assert "u" * 8191 + "\u20ac" in text
        assert "\ufffd" not in text
        assert "oversized-start" not in text and "oversized-end" not in text
        assert "recovered" in text and "tail \u20ac" in text
        assert "omitted" in text.lower()
        gui_text = (log_dir / "gui.log").read_text(encoding="utf-8")
        assert "recovered" in gui_text and secret not in gui_text
    finally:
        hermes_logging._reset_queued_handlers()


def test_source_launch_keeps_interactive_streams():
    with desktop_console_output(source_mode=True) as streams:
        assert streams == {}
