# Projects/veritell-langchain/tests/test_client_fail_open_integration.py
import pytest

from veritell_langchain.client import VeritellClient
from veritell_langchain.errors import (
    RateLimitedError,
    ServiceUnavailableError,
    VeritellTimeoutError,
)
from veritell_langchain.http import HttpResponse
from veritell_langchain.schema import SCHEMA_VERSION, VeritellEvaluationResult


class FakeHttpClient:
    def __init__(self, *, response: HttpResponse | None = None, exc: Exception | None = None):
        self._response = response
        self._exc = exc

    def post(self, url: str, *, json, headers=None, timeout_s=None) -> HttpResponse:
        if self._exc is not None:
            raise self._exc
        assert self._response is not None
        return self._response


def test_client_fail_open_false_raises_timeout() -> None:
    client = VeritellClient(
        http_client=FakeHttpClient(exc=TimeoutError("t")),
        base_url="https://example.test",
        fail_open=False,
    )
    with pytest.raises(VeritellTimeoutError):
        client.evaluate(payload={"x": 1})


def test_client_fail_open_true_returns_default_on_timeout() -> None:
    client = VeritellClient(
        http_client=FakeHttpClient(exc=TimeoutError("t")),
        base_url="https://example.test",
        fail_open=True,
    )
    result = client.evaluate(payload={"x": 1})
    assert isinstance(result, VeritellEvaluationResult)
    assert result.schema_version == SCHEMA_VERSION
    assert result.extra.get("fail_open") is True
    assert result.extra.get("reason") == "timeout"


def test_client_fail_open_false_raises_503() -> None:
    client = VeritellClient(
        http_client=FakeHttpClient(response=HttpResponse(status_code=503, json_data={"x": 1})),
        base_url="https://example.test",
        fail_open=False,
    )
    with pytest.raises(ServiceUnavailableError):
        client.evaluate(payload={"x": 1})


def test_client_fail_open_true_returns_default_on_503() -> None:
    client = VeritellClient(
        http_client=FakeHttpClient(response=HttpResponse(status_code=503, json_data={"x": 1})),
        base_url="https://example.test",
        fail_open=True,
    )
    result = client.evaluate(payload={"x": 1})
    assert result.schema_version == SCHEMA_VERSION
    assert result.extra.get("fail_open") is True
    assert result.extra.get("reason") == "service_unavailable"


def test_client_fail_open_false_raises_429() -> None:
    client = VeritellClient(
        http_client=FakeHttpClient(response=HttpResponse(status_code=429, json_data={"x": 1})),
        base_url="https://example.test",
        fail_open=False,
    )
    with pytest.raises(RateLimitedError):
        client.evaluate(payload={"x": 1})


def test_client_fail_open_true_returns_default_on_429() -> None:
    client = VeritellClient(
        http_client=FakeHttpClient(response=HttpResponse(status_code=429, json_data={"x": 1})),
        base_url="https://example.test",
        fail_open=True,
    )
    result = client.evaluate(payload={"x": 1})
    assert result.schema_version == SCHEMA_VERSION
    assert result.extra.get("fail_open") is True
    assert result.extra.get("reason") == "rate_limited"
