from __future__ import annotations

from bootstrap import telemetry


def test_post_does_not_warn_on_non_retryable_413(monkeypatch, capsys) -> None:
    def fake_urlopen_with_retries(
        req,
        timeout_seconds: int,
        attempts: int,
        base_delay_seconds: float,
        non_retryable_statuses: set[int] | None = None,
    ) -> tuple[bool, int | None]:
        return False, 413

    monkeypatch.setattr(telemetry, "_urlopen_with_retries", fake_urlopen_with_retries)

    success, status = telemetry._post(
        "http://example.test/runs/logs",
        "token",
        {"message": "hello"},
        non_retryable_statuses={413},
    )

    captured = capsys.readouterr()
    assert success is False
    assert status == 413
    assert captured.err == ""


def test_post_log_sends_placeholder_on_413(monkeypatch) -> None:
    calls: list[tuple[str, str, dict, dict]] = []

    def fake_post(url: str, token: str, body: dict, **kwargs):
        calls.append((url, token, body, kwargs))
        if len(calls) == 1:
            return False, 413
        return True, 202

    monkeypatch.setattr(telemetry, "_post", fake_post)

    telemetry.post_log(
        "http://example.test",
        "run-123",
        "token",
        "info",
        "hello",
        {"foo": "bar"},
    )

    assert len(calls) == 2
    assert calls[0][3]["non_retryable_statuses"] == {413}

    placeholder = calls[1][2]
    assert placeholder["message"] == telemetry.LOG_DROPPED_MESSAGE
    assert placeholder["level"] == "warning"
    extra = placeholder["extra"]
    assert extra["dropped"] is True
    assert extra["drop_reason"] == "payload_too_large"
    assert extra["original_level"] == "info"
    assert extra["message_bytes"] == len("hello".encode("utf-8"))
    assert extra["limit_bytes"] == telemetry.MAX_LOG_MESSAGE_BYTES
    assert calls[1][3]["attempts"] == 1
    assert calls[1][3]["base_delay_seconds"] == 0


def test_poll_run_control_calls_expected_endpoint(monkeypatch) -> None:
    captured: dict[str, object] = {}

    def fake_urlopen_json_with_retries(
        req, timeout_seconds, attempts, base_delay_seconds
    ):
        captured["url"] = req.full_url
        captured["token"] = req.headers.get("X-run-token")
        captured["method"] = req.get_method()
        return {"run_id": "run-1", "command": None}

    monkeypatch.setattr(
        telemetry, "_urlopen_json_with_retries", fake_urlopen_json_with_retries
    )

    result = telemetry.poll_run_control("http://example.test", "run-1", "token-123")

    assert result["run_id"] == "run-1"
    assert captured["url"] == "http://example.test/runs/run-1/control/poll"
    assert captured["method"] == "GET"
    assert captured["token"] == "token-123"


def test_ack_run_control_posts_expected_payload(monkeypatch) -> None:
    captured: list[tuple[str, str, dict[str, object]]] = []

    def fake_post(url: str, token: str, body: dict[str, object], **kwargs):
        captured.append((url, token, body))
        return True, 200

    monkeypatch.setattr(telemetry, "_post", fake_post)

    telemetry.ack_run_control(
        "http://example.test",
        "run-1",
        "token-123",
        command_id="cmd-1",
        status="applied",
        detail="ok",
    )

    assert captured == [
        (
            "http://example.test/runs/run-1/control/ack",
            "token-123",
            {"command_id": "cmd-1", "status": "applied", "detail": "ok"},
        )
    ]
