"""Tests for ``mgf.apiprobe.checks.observability``."""

from __future__ import annotations

from tests.unit.checks.conftest import empty_ctx, make_response

from mgf.apiprobe.checks.observability import (
    MissingRateLimitHeaders,
    MissingRequestId,
    MissingServerHeader,
)
from mgf.apiprobe.core.finding import RootCause, Severity
from mgf.apiprobe.core.probe import Probe


class TestMissingRequestId:
    def test_silent_with_x_request_id(self) -> None:
        probe = Probe.get("https://x/y").id("p1")
        resp = make_response(headers={"X-Request-Id": "abc"})
        findings = list(MissingRequestId().run(probe, resp, empty_ctx()))
        assert findings == []

    def test_silent_with_cf_ray(self) -> None:
        probe = Probe.get("https://x/y").id("p1")
        resp = make_response(headers={"Cf-Ray": "01234"})
        findings = list(MissingRequestId().run(probe, resp, empty_ctx()))
        assert findings == []

    def test_silent_with_amz_request_id(self) -> None:
        probe = Probe.get("https://x/y").id("p1")
        resp = make_response(headers={"X-Amz-Request-Id": "0EXAMPLE"})
        findings = list(MissingRequestId().run(probe, resp, empty_ctx()))
        assert findings == []

    def test_emits_when_no_known_request_id_header(self) -> None:
        probe = Probe.get("https://x/y").id("p1")
        findings = list(MissingRequestId().run(probe, make_response(), empty_ctx()))
        assert len(findings) == 1
        f = findings[0]
        assert f.code == "observability.headers.missing-request-id"
        assert f.severity is Severity.WARN
        assert f.root_cause is RootCause.PROVIDER_OBSERVABILITY


class TestMissingRateLimitHeaders:
    def test_silent_on_non_429(self) -> None:
        probe = Probe.get("https://x/y").id("p1")
        resp = make_response(status=200)
        findings = list(MissingRateLimitHeaders().run(probe, resp, empty_ctx()))
        assert findings == []

    def test_silent_when_retry_after_present(self) -> None:
        probe = Probe.get("https://x/y").id("p1")
        resp = make_response(status=429, headers={"Retry-After": "60"})
        findings = list(MissingRateLimitHeaders().run(probe, resp, empty_ctx()))
        assert findings == []

    def test_silent_when_x_ratelimit_present(self) -> None:
        probe = Probe.get("https://x/y").id("p1")
        resp = make_response(status=429, headers={"X-RateLimit-Limit": "100"})
        findings = list(MissingRateLimitHeaders().run(probe, resp, empty_ctx()))
        assert findings == []

    def test_emits_on_429_without_headers(self) -> None:
        probe = Probe.get("https://x/y").id("p1")
        resp = make_response(status=429)
        findings = list(MissingRateLimitHeaders().run(probe, resp, empty_ctx()))
        assert len(findings) == 1
        f = findings[0]
        # This check overrides root_cause to RATE_LIMIT (the default
        # was PROVIDER_OBSERVABILITY but rate-limit-on-429 is more specific).
        assert f.root_cause is RootCause.RATE_LIMIT
        assert f.severity is Severity.WARN


class TestMissingServerHeader:
    def test_silent_with_server(self) -> None:
        probe = Probe.get("https://x/y").id("p1")
        resp = make_response(headers={"Server": "nginx/1.24"})
        findings = list(MissingServerHeader().run(probe, resp, empty_ctx()))
        assert findings == []

    def test_silent_with_via(self) -> None:
        probe = Probe.get("https://x/y").id("p1")
        resp = make_response(headers={"Via": "1.1 cloudfront"})
        findings = list(MissingServerHeader().run(probe, resp, empty_ctx()))
        assert findings == []

    def test_emits_when_neither(self) -> None:
        probe = Probe.get("https://x/y").id("p1")
        findings = list(MissingServerHeader().run(probe, make_response(), empty_ctx()))
        assert len(findings) == 1
        assert findings[0].severity is Severity.INFO  # informational
