"""Tests for remote/marketplace device routing in BackendDispatcher.

Covers:
- Remote backend selection and forwarding via _dispatch_remote
- Retry/fallback when a remote device fails
- RemitConfig allowlist/denylist enforcement
- Health marking on failure (healthy=False)
- Streaming response forwarding via _stream_remote
- ProbeStore health integration
- Billing event emission after remote dispatch
- Remote response headers (X-LLMHosts-Remote, X-LLMHosts-Device-Id)
"""

from __future__ import annotations

from typing import Any
from unittest.mock import AsyncMock, MagicMock

import httpx
import pytest

from llmhosts.config import LLMHostsConfig, RemitConfig
from llmhosts.proxy.dispatcher import REMOTE_TIMEOUT, BackendDispatcher, BackendEntry
from llmhosts.proxy.errors import BackendTimeoutError, BackendUnavailableError
from llmhosts.proxy.models import UnifiedMessage, UnifiedRequest

# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------

_OPENAI_COMPAT_RESPONSE = {
    "id": "chatcmpl-remote-1",
    "object": "chat.completion",
    "created": 1234567890,
    "model": "llama3.2:8b",
    "choices": [
        {
            "index": 0,
            "message": {"role": "assistant", "content": "Hello from remote"},
            "finish_reason": "stop",
        }
    ],
    "usage": {"prompt_tokens": 10, "completion_tokens": 5, "total_tokens": 15},
}


def _make_request(model: str = "llama3.2:8b") -> UnifiedRequest:
    return UnifiedRequest(
        model=model,
        messages=[UnifiedMessage(role="user", content="Hello")],
        stream=False,
    )


def _mock_httpx_response(
    json_body: dict[str, Any] | None = None,
    status_code: int = 200,
    base_url: str = "https://remote.example.com",
) -> httpx.Response:
    body = json_body or _OPENAI_COMPAT_RESPONSE
    return httpx.Response(
        status_code=status_code,
        json=body,
        request=httpx.Request("POST", f"{base_url}/v1/chat/completions"),
    )


async def _setup_dispatcher_with_remote(
    *,
    tunnel_url: str = "https://remote.example.com",
    name: str = "remote-node-1",
    models: list[str] | None = None,
    device_id: str = "device-001",
    config: LLMHostsConfig | None = None,
    remote_timeout: float = REMOTE_TIMEOUT,
) -> BackendDispatcher:
    """Create a dispatcher with a single remote backend registered."""
    dispatcher = BackendDispatcher(config=config, remote_timeout=remote_timeout)
    await dispatcher.startup()
    dispatcher.register_remote_backend(
        tunnel_url=tunnel_url,
        name=name,
        models=models or ["llama3.2:8b"],
        device_id=device_id,
    )
    return dispatcher


# ---------------------------------------------------------------------------
# 1. Remote backend selection and forwarding
# ---------------------------------------------------------------------------


@pytest.mark.unit
async def test_remote_backend_is_selected_for_matching_model() -> None:
    """A remote backend is selected when it's the only one serving the model."""
    dispatcher = await _setup_dispatcher_with_remote()
    candidates = dispatcher._get_remote_candidates("llama3.2:8b")
    assert len(candidates) == 1
    assert candidates[0].backend_type == "remote"
    assert candidates[0].device_id == "device-001"


@pytest.mark.unit
async def test_remote_backend_not_selected_for_wrong_model() -> None:
    """Remote backend is not a candidate when it doesn't serve the requested model."""
    dispatcher = await _setup_dispatcher_with_remote(models=["mistral:7b"])
    candidates = dispatcher._get_remote_candidates("llama3.2:8b")
    assert len(candidates) == 0


@pytest.mark.unit
async def test_dispatch_remote_forwards_to_tunnel_url() -> None:
    """_dispatch_remote sends POST to {tunnel_url}/v1/chat/completions."""
    dispatcher = await _setup_dispatcher_with_remote()
    backend = next(b for b in dispatcher._backends if b.backend_type == "remote")
    client = dispatcher._get_or_create_pool(backend)
    client.post = AsyncMock(return_value=_mock_httpx_response())

    response, _headers = await dispatcher._dispatch_remote(backend, _make_request())
    assert response.content == "Hello from remote"
    assert response.prompt_tokens == 10
    assert response.completion_tokens == 5
    assert response.total_tokens == 15
    # Verify the call URL
    call_args = client.post.call_args
    assert "/v1/chat/completions" in call_args.args[0]


@pytest.mark.unit
async def test_dispatch_remote_returns_extra_headers() -> None:
    """_dispatch_remote returns X-LLMHosts-Remote and X-LLMHosts-Device-Id headers."""
    dispatcher = await _setup_dispatcher_with_remote(device_id="dev-xyz")
    backend = next(b for b in dispatcher._backends if b.backend_type == "remote")
    client = dispatcher._get_or_create_pool(backend)
    client.post = AsyncMock(return_value=_mock_httpx_response())

    _, headers = await dispatcher._dispatch_remote(backend, _make_request())
    assert headers["X-LLMHosts-Remote"] == "true"
    assert headers["X-LLMHosts-Device-Id"] == "dev-xyz"


@pytest.mark.unit
async def test_dispatch_remote_uses_configured_timeout() -> None:
    """_dispatch_remote passes the configurable remote_timeout to httpx."""
    dispatcher = await _setup_dispatcher_with_remote(remote_timeout=45.0)
    backend = next(b for b in dispatcher._backends if b.backend_type == "remote")
    client = dispatcher._get_or_create_pool(backend)
    client.post = AsyncMock(return_value=_mock_httpx_response())

    await dispatcher._dispatch_remote(backend, _make_request())
    call_kwargs = client.post.call_args.kwargs
    assert call_kwargs.get("timeout") == 45.0


@pytest.mark.unit
async def test_dispatch_remote_empty_choices() -> None:
    """_dispatch_remote handles empty choices gracefully."""
    dispatcher = await _setup_dispatcher_with_remote()
    backend = next(b for b in dispatcher._backends if b.backend_type == "remote")
    client = dispatcher._get_or_create_pool(backend)
    empty_resp = {**_OPENAI_COMPAT_RESPONSE, "choices": []}
    client.post = AsyncMock(return_value=_mock_httpx_response(json_body=empty_resp))

    response, _ = await dispatcher._dispatch_remote(backend, _make_request())
    assert response.content == ""
    assert response.finish_reason == "stop"


# ---------------------------------------------------------------------------
# 2. Health marking on failure
# ---------------------------------------------------------------------------


@pytest.mark.unit
async def test_remote_timeout_marks_unhealthy() -> None:
    """Timeout on a remote backend sets healthy=False."""
    dispatcher = await _setup_dispatcher_with_remote()
    backend = next(b for b in dispatcher._backends if b.backend_type == "remote")
    client = dispatcher._get_or_create_pool(backend)
    client.post = AsyncMock(side_effect=httpx.TimeoutException("timed out"))

    assert backend.healthy is True
    with pytest.raises(BackendTimeoutError):
        await dispatcher._dispatch_remote(backend, _make_request())
    assert backend.healthy is False


@pytest.mark.unit
async def test_remote_connect_error_marks_unhealthy() -> None:
    """Connection error on a remote backend sets healthy=False."""
    dispatcher = await _setup_dispatcher_with_remote()
    backend = next(b for b in dispatcher._backends if b.backend_type == "remote")
    client = dispatcher._get_or_create_pool(backend)
    client.post = AsyncMock(side_effect=httpx.ConnectError("refused"))

    assert backend.healthy is True
    with pytest.raises(BackendUnavailableError):
        await dispatcher._dispatch_remote(backend, _make_request())
    assert backend.healthy is False


@pytest.mark.unit
async def test_remote_http_error_does_not_mark_unhealthy() -> None:
    """HTTP 500 from remote does not set healthy=False (server error, not transport)."""
    dispatcher = await _setup_dispatcher_with_remote()
    backend = next(b for b in dispatcher._backends if b.backend_type == "remote")
    client = dispatcher._get_or_create_pool(backend)
    error_response = httpx.Response(
        status_code=500,
        text="Internal Server Error",
        request=httpx.Request("POST", "https://remote.example.com/v1/chat/completions"),
    )
    client.post = AsyncMock(
        side_effect=httpx.HTTPStatusError("500", request=error_response.request, response=error_response)
    )

    with pytest.raises(BackendUnavailableError):
        await dispatcher._dispatch_remote(backend, _make_request())
    # HTTP errors don't mark unhealthy — it's the backend's app, not transport
    assert backend.healthy is True


# ---------------------------------------------------------------------------
# 3. Retry logic (_dispatch_remote_with_retry)
# ---------------------------------------------------------------------------


@pytest.mark.unit
async def test_retry_falls_through_to_second_remote() -> None:
    """When first remote fails, _dispatch_remote_with_retry tries the second."""
    dispatcher = await _setup_dispatcher_with_remote(
        tunnel_url="https://node1.example.com",
        name="remote-1",
        device_id="dev-1",
    )
    dispatcher.register_remote_backend(
        tunnel_url="https://node2.example.com",
        name="remote-2",
        models=["llama3.2:8b"],
        device_id="dev-2",
    )

    # Make first backend fail, second succeed
    node1 = next(b for b in dispatcher._backends if b.name == "remote-1")
    node2 = next(b for b in dispatcher._backends if b.name == "remote-2")

    client1 = dispatcher._get_or_create_pool(node1)
    client2 = dispatcher._get_or_create_pool(node2)

    client1.post = AsyncMock(side_effect=httpx.ConnectError("refused"))
    client2.post = AsyncMock(return_value=_mock_httpx_response(base_url="https://node2.example.com"))

    response, used_backend, headers = await dispatcher._dispatch_remote_with_retry(
        _make_request(), request_id="req-retry"
    )
    assert response.content == "Hello from remote"
    assert used_backend.name == "remote-2"
    assert headers["X-LLMHosts-Device-Id"] == "dev-2"
    # First backend should be marked unhealthy
    assert node1.healthy is False


@pytest.mark.unit
async def test_retry_raises_when_all_fail() -> None:
    """When all remote candidates fail, BackendUnavailableError is raised."""
    dispatcher = await _setup_dispatcher_with_remote(
        tunnel_url="https://fail1.example.com",
        name="remote-fail-1",
        device_id="dev-fail-1",
    )
    dispatcher.register_remote_backend(
        tunnel_url="https://fail2.example.com",
        name="remote-fail-2",
        models=["llama3.2:8b"],
        device_id="dev-fail-2",
    )

    for b in dispatcher._backends:
        if b.backend_type == "remote":
            client = dispatcher._get_or_create_pool(b)
            client.post = AsyncMock(side_effect=httpx.ConnectError("refused"))

    with pytest.raises(BackendUnavailableError, match="All remote devices failed"):
        await dispatcher._dispatch_remote_with_retry(_make_request())


@pytest.mark.unit
async def test_retry_skips_unhealthy_backends() -> None:
    """Backends already marked unhealthy are not attempted during retry."""
    dispatcher = await _setup_dispatcher_with_remote(
        tunnel_url="https://node-a.example.com",
        name="remote-a",
        device_id="dev-a",
    )
    dispatcher.register_remote_backend(
        tunnel_url="https://node-b.example.com",
        name="remote-b",
        models=["llama3.2:8b"],
        device_id="dev-b",
    )

    node_a = next(b for b in dispatcher._backends if b.name == "remote-a")
    node_a.healthy = False  # pre-mark as unhealthy

    node_b = next(b for b in dispatcher._backends if b.name == "remote-b")
    client_b = dispatcher._get_or_create_pool(node_b)
    client_b.post = AsyncMock(return_value=_mock_httpx_response(base_url="https://node-b.example.com"))

    _response, used, _ = await dispatcher._dispatch_remote_with_retry(_make_request())
    assert used.name == "remote-b"


# ---------------------------------------------------------------------------
# 4. Remit allowlist/denylist enforcement
# ---------------------------------------------------------------------------


@pytest.mark.unit
async def test_remit_allowlist_blocks_unallowed_device() -> None:
    """RemitConfig allowlist blocks device_ids not in the list."""
    config = LLMHostsConfig(remit=RemitConfig(mode="allowlist", allowlist=["dev-allowed"]))
    dispatcher = BackendDispatcher(config=config)
    await dispatcher.startup()

    # Register two remotes: one allowed, one not
    dispatcher.register_remote_backend(
        tunnel_url="https://allowed.example.com",
        name="remote-allowed",
        models=["llama3.2:8b"],
        device_id="dev-allowed",
    )
    dispatcher.register_remote_backend(
        tunnel_url="https://blocked.example.com",
        name="remote-blocked",
        models=["llama3.2:8b"],
        device_id="dev-blocked",
    )

    candidates = dispatcher._get_remote_candidates("llama3.2:8b")
    device_ids = {c.device_id for c in candidates}
    assert "dev-allowed" in device_ids
    assert "dev-blocked" not in device_ids


@pytest.mark.unit
async def test_remit_denylist_blocks_denied_device() -> None:
    """RemitConfig denylist blocks specific device_ids."""
    config = LLMHostsConfig(remit=RemitConfig(mode="denylist", denylist=["dev-bad"]))
    dispatcher = BackendDispatcher(config=config)
    await dispatcher.startup()

    dispatcher.register_remote_backend(
        tunnel_url="https://good.example.com",
        name="remote-good",
        models=["llama3.2:8b"],
        device_id="dev-good",
    )
    dispatcher.register_remote_backend(
        tunnel_url="https://bad.example.com",
        name="remote-bad",
        models=["llama3.2:8b"],
        device_id="dev-bad",
    )

    candidates = dispatcher._get_remote_candidates("llama3.2:8b")
    device_ids = {c.device_id for c in candidates}
    assert "dev-good" in device_ids
    assert "dev-bad" not in device_ids


@pytest.mark.unit
async def test_remit_mode_all_allows_everything() -> None:
    """RemitConfig mode=all allows all remote devices."""
    config = LLMHostsConfig(remit=RemitConfig(mode="all"))
    dispatcher = BackendDispatcher(config=config)
    await dispatcher.startup()

    dispatcher.register_remote_backend(
        tunnel_url="https://any.example.com",
        name="remote-any",
        models=["llama3.2:8b"],
        device_id="dev-any",
    )

    candidates = dispatcher._get_remote_candidates("llama3.2:8b")
    assert len(candidates) == 1


@pytest.mark.unit
async def test_remit_allowlist_empty_allows_all() -> None:
    """Empty allowlist with mode=allowlist allows all devices."""
    config = LLMHostsConfig(remit=RemitConfig(mode="allowlist", allowlist=[]))
    dispatcher = BackendDispatcher(config=config)
    await dispatcher.startup()

    dispatcher.register_remote_backend(
        tunnel_url="https://x.example.com",
        name="remote-x",
        models=["llama3.2:8b"],
        device_id="dev-x",
    )

    candidates = dispatcher._get_remote_candidates("llama3.2:8b")
    assert len(candidates) == 1


@pytest.mark.unit
async def test_remit_denylist_by_name() -> None:
    """RemitConfig denylist can also block by backend name."""
    config = LLMHostsConfig(remit=RemitConfig(mode="denylist", denylist=["remote-blocked"]))
    dispatcher = BackendDispatcher(config=config)
    await dispatcher.startup()

    dispatcher.register_remote_backend(
        tunnel_url="https://blocked.example.com",
        name="remote-blocked",
        models=["llama3.2:8b"],
        device_id="dev-123",
    )

    candidates = dispatcher._get_remote_candidates("llama3.2:8b")
    assert len(candidates) == 0


# ---------------------------------------------------------------------------
# 5. ProbeStore health integration
# ---------------------------------------------------------------------------


@pytest.mark.unit
async def test_probe_store_low_uptime_filters_candidate() -> None:
    """Backend with <50% uptime in ProbeStore is excluded from candidates."""
    dispatcher = await _setup_dispatcher_with_remote(device_id="dev-low")

    probe_store = AsyncMock()
    probe_store.get_uptime_pct = AsyncMock(return_value=30.0)
    dispatcher.attach_probe_store(probe_store)

    backend = next(b for b in dispatcher._backends if b.backend_type == "remote")
    assert await dispatcher._is_remote_healthy(backend) is False


@pytest.mark.unit
async def test_probe_store_high_uptime_allows_candidate() -> None:
    """Backend with >=50% uptime in ProbeStore is considered healthy."""
    dispatcher = await _setup_dispatcher_with_remote(device_id="dev-high")

    probe_store = AsyncMock()
    probe_store.get_uptime_pct = AsyncMock(return_value=95.0)
    dispatcher.attach_probe_store(probe_store)

    backend = next(b for b in dispatcher._backends if b.backend_type == "remote")
    assert await dispatcher._is_remote_healthy(backend) is True


@pytest.mark.unit
async def test_probe_store_no_data_assumes_healthy() -> None:
    """New device with no probe data is assumed healthy (grace period)."""
    dispatcher = await _setup_dispatcher_with_remote(device_id="dev-new")

    probe_store = AsyncMock()
    probe_store.get_uptime_pct = AsyncMock(return_value=None)
    dispatcher.attach_probe_store(probe_store)

    backend = next(b for b in dispatcher._backends if b.backend_type == "remote")
    assert await dispatcher._is_remote_healthy(backend) is True


@pytest.mark.unit
async def test_probe_store_query_error_assumes_healthy() -> None:
    """If ProbeStore query fails, assume the device is healthy."""
    dispatcher = await _setup_dispatcher_with_remote(device_id="dev-err")

    probe_store = AsyncMock()
    probe_store.get_uptime_pct = AsyncMock(side_effect=RuntimeError("db error"))
    dispatcher.attach_probe_store(probe_store)

    backend = next(b for b in dispatcher._backends if b.backend_type == "remote")
    assert await dispatcher._is_remote_healthy(backend) is True


@pytest.mark.unit
async def test_no_probe_store_always_healthy() -> None:
    """Without a ProbeStore attached, remote backends are healthy if their flag is True."""
    dispatcher = await _setup_dispatcher_with_remote()
    backend = next(b for b in dispatcher._backends if b.backend_type == "remote")
    assert await dispatcher._is_remote_healthy(backend) is True


# ---------------------------------------------------------------------------
# 6. Full dispatch() integration — remote path
# ---------------------------------------------------------------------------


@pytest.mark.unit
async def test_full_dispatch_remote_sets_response_headers() -> None:
    """dispatch() for a remote backend puts remote_headers into response.extra."""
    dispatcher = await _setup_dispatcher_with_remote(device_id="dev-full")
    backend = next(b for b in dispatcher._backends if b.backend_type == "remote")
    client = dispatcher._get_or_create_pool(backend)
    client.post = AsyncMock(return_value=_mock_httpx_response())

    response = await dispatcher.dispatch(
        _make_request(),
        request_id="req-full",
    )
    assert response.content == "Hello from remote"
    assert response.extra is not None
    assert response.extra.get("remote_headers", {}).get("X-LLMHosts-Remote") == "true"
    assert response.extra.get("remote_headers", {}).get("X-LLMHosts-Device-Id") == "dev-full"


@pytest.mark.unit
async def test_full_dispatch_remote_emits_billing_event() -> None:
    """dispatch() emits a billing event for remote backend completions."""
    dispatcher = await _setup_dispatcher_with_remote(device_id="dev-bill")
    backend = next(b for b in dispatcher._backends if b.backend_type == "remote")
    client = dispatcher._get_or_create_pool(backend)
    client.post = AsyncMock(return_value=_mock_httpx_response())

    events: list[dict[str, Any]] = []
    dispatcher.attach_billing_callback(lambda e: events.append(e))

    await dispatcher.dispatch(
        _make_request(),
        request_id="req-bill",
        api_key_id="key-001",
        user_id="user-001",
    )
    assert len(events) == 1
    assert events[0]["device_id"] == "dev-bill"
    assert events[0]["model"] == "llama3.2:8b"
    assert events[0]["total_tokens"] == 15


@pytest.mark.unit
async def test_full_dispatch_remote_retry_on_failure() -> None:
    """dispatch() retries across remote backends when the first fails."""
    config = LLMHostsConfig()
    dispatcher = BackendDispatcher(config=config)
    await dispatcher.startup()

    dispatcher.register_remote_backend(
        tunnel_url="https://fail.example.com",
        name="remote-fail",
        models=["llama3.2:8b"],
        device_id="dev-fail",
        priority=1,
    )
    dispatcher.register_remote_backend(
        tunnel_url="https://ok.example.com",
        name="remote-ok",
        models=["llama3.2:8b"],
        device_id="dev-ok",
        priority=2,
    )

    fail_backend = next(b for b in dispatcher._backends if b.name == "remote-fail")
    ok_backend = next(b for b in dispatcher._backends if b.name == "remote-ok")

    fail_client = dispatcher._get_or_create_pool(fail_backend)
    ok_client = dispatcher._get_or_create_pool(ok_backend)

    fail_client.post = AsyncMock(side_effect=httpx.TimeoutException("timeout"))
    ok_client.post = AsyncMock(return_value=_mock_httpx_response(base_url="https://ok.example.com"))

    response = await dispatcher.dispatch(_make_request(), request_id="req-retry-full")
    assert response.content == "Hello from remote"
    assert response.extra is not None
    assert response.extra["remote_headers"]["X-LLMHosts-Device-Id"] == "dev-ok"


# ---------------------------------------------------------------------------
# 7. Streaming remote dispatch
# ---------------------------------------------------------------------------


@pytest.mark.unit
async def test_stream_remote_yields_tokens() -> None:
    """_stream_remote yields tokens from SSE chunks."""
    dispatcher = await _setup_dispatcher_with_remote()
    backend = next(b for b in dispatcher._backends if b.backend_type == "remote")
    client = dispatcher._get_or_create_pool(backend)

    sse_lines = [
        'data: {"choices": [{"delta": {"content": "Hello"}, "finish_reason": null}]}',
        'data: {"choices": [{"delta": {"content": " world"}, "finish_reason": null}]}',
        'data: {"choices": [{"delta": {"content": ""}, "finish_reason": "stop"}]}',
        "data: [DONE]",
    ]

    # Create an async context manager mock for client.stream
    mock_response = AsyncMock()
    mock_response.raise_for_status = MagicMock()

    async def _aiter_lines():
        for line in sse_lines:
            yield line

    mock_response.aiter_lines = _aiter_lines
    mock_stream_cm = AsyncMock()
    mock_stream_cm.__aenter__ = AsyncMock(return_value=mock_response)
    mock_stream_cm.__aexit__ = AsyncMock(return_value=False)

    client.stream = MagicMock(return_value=mock_stream_cm)

    tokens: list[str] = []
    async for token in dispatcher._stream_remote(backend, _make_request()):
        tokens.append(token)
    assert tokens == ["Hello", " world"]


@pytest.mark.unit
async def test_stream_remote_timeout_marks_unhealthy() -> None:
    """Streaming timeout marks remote backend unhealthy."""
    dispatcher = await _setup_dispatcher_with_remote()
    backend = next(b for b in dispatcher._backends if b.backend_type == "remote")
    client = dispatcher._get_or_create_pool(backend)

    mock_stream_cm = AsyncMock()
    mock_stream_cm.__aenter__ = AsyncMock(side_effect=httpx.TimeoutException("stream timeout"))
    mock_stream_cm.__aexit__ = AsyncMock(return_value=False)
    client.stream = MagicMock(return_value=mock_stream_cm)

    with pytest.raises(BackendTimeoutError):
        async for _ in dispatcher._stream_remote(backend, _make_request()):
            pass
    assert backend.healthy is False


# ---------------------------------------------------------------------------
# 8. Remote timeout configuration
# ---------------------------------------------------------------------------


@pytest.mark.unit
async def test_default_remote_timeout() -> None:
    """Default remote timeout is REMOTE_TIMEOUT constant (30s)."""
    dispatcher = BackendDispatcher()
    assert dispatcher._remote_timeout == REMOTE_TIMEOUT
    assert dispatcher._remote_timeout == 30.0


@pytest.mark.unit
async def test_custom_remote_timeout() -> None:
    """Remote timeout can be configured via constructor."""
    dispatcher = BackendDispatcher(remote_timeout=60.0)
    assert dispatcher._remote_timeout == 60.0


# ---------------------------------------------------------------------------
# 9. _is_device_in_remit edge cases
# ---------------------------------------------------------------------------


@pytest.mark.unit
async def test_is_device_in_remit_non_remote_always_passes() -> None:
    """Non-remote backends always pass the device remit check."""
    config = LLMHostsConfig(remit=RemitConfig(mode="allowlist", allowlist=["only-this"]))
    dispatcher = BackendDispatcher(config=config)
    ollama_entry = BackendEntry(
        name="ollama-local",
        base_url="http://127.0.0.1:11434",
        backend_type="ollama",
        models=["llama3.2:8b"],
    )
    assert dispatcher._is_device_in_remit(ollama_entry) is True


@pytest.mark.unit
async def test_is_device_in_remit_unknown_mode_allows() -> None:
    """Unknown remit mode defaults to allow."""
    config = LLMHostsConfig(remit=RemitConfig(mode="custom-mode"))
    dispatcher = BackendDispatcher(config=config)
    entry = BackendEntry(
        name="remote-x",
        base_url="https://x.example.com",
        backend_type="remote",
        device_id="dev-x",
    )
    assert dispatcher._is_device_in_remit(entry) is True
