from __future__ import annotations

import httpx
import pytest

from email_enrichment.reacher import ReacherClient, Retryable

SAFE_PAYLOAD = {
    "input": "jon@dasaninc.com",
    "is_reachable": "safe",
    "smtp": {
        "is_catch_all": False,
        "verif_method": {"type": "Smtp", "host": "mx.dasaninc.com"},
    },
    "misc": {"is_disposable": False, "is_role_account": False},
    "debug": {"duration": {"secs": 1, "nanos": 337000000}},
}


def _client_with(transport: httpx.MockTransport) -> ReacherClient:
    c = ReacherClient(secret="dummy", max_per_minute=60)
    c._client.close()
    c._client = httpx.Client(transport=transport, headers=c._headers, timeout=5.0)
    return c


def test_requires_secret(monkeypatch: pytest.MonkeyPatch) -> None:
    monkeypatch.delenv("REACHER_SECRET", raising=False)
    with pytest.raises(RuntimeError, match="REACHER_SECRET"):
        ReacherClient()


def test_check_email_safe() -> None:
    def handler(request: httpx.Request) -> httpx.Response:
        assert request.headers["x-reacher-secret"] == "dummy"
        assert request.url.path == "/v1/check_email"
        return httpx.Response(200, json=SAFE_PAYLOAD)

    with _client_with(httpx.MockTransport(handler)) as c:
        res = c.check_email("jon@dasaninc.com")
    assert res.verdict == "safe"
    assert res.smtp_method == "Smtp"
    assert res.is_role_account is False
    assert res.duration_ms is not None and res.duration_ms >= 1000


def test_http_4xx_returns_unknown() -> None:
    def handler(request: httpx.Request) -> httpx.Response:
        return httpx.Response(400, text="bad request")

    with _client_with(httpx.MockTransport(handler)) as c:
        res = c.check_email("broken@example.com")
    assert res.verdict == "unknown"
    assert res.raw["http_status"] == 400


def test_retries_on_429_then_succeeds() -> None:
    calls = {"n": 0}

    def handler(request: httpx.Request) -> httpx.Response:
        calls["n"] += 1
        if calls["n"] < 3:
            return httpx.Response(429, text="slow down")
        return httpx.Response(200, json=SAFE_PAYLOAD)

    with _client_with(httpx.MockTransport(handler)) as c:
        res = c.check_email("jon@dasaninc.com")
    assert res.verdict == "safe"
    assert calls["n"] == 3


def test_giveup_after_max_attempts() -> None:
    def handler(request: httpx.Request) -> httpx.Response:
        return httpx.Response(503, text="unavailable")

    with _client_with(httpx.MockTransport(handler)) as c, pytest.raises(Retryable):
        c.check_email("jon@dasaninc.com")
