"""Peer endpoints: hello is open, status/ask need the PSK, loop guard works."""

from types import SimpleNamespace

import pytest
from fastapi import FastAPI
from fastapi.testclient import TestClient

from navi import swarm
from navi.api.routes import peer as peer_routes
from navi.identity import ensure_identity

KEY = "secret-key-123"


@pytest.fixture()
def peer_env(tmp_path, monkeypatch):
    """Real instance.json + .swarm-key in tmp; settings point there."""
    import navi.api.deps  # noqa: F401 - resolve the container BEFORE settings are swapped

    ensure_identity(tmp_path / "instance.json")
    (tmp_path / ".swarm-key").write_text(KEY)
    fake = SimpleNamespace(
        instance_file=str(tmp_path / "instance.json"),
        swarm_key_file=str(tmp_path / ".swarm-key"),
        peer_ask_profile="server_admin",
        peer_ask_timeout_sec=5,
        navi_port=8099,
    )
    monkeypatch.setattr(peer_routes, "settings", fake)
    monkeypatch.setattr("navi.config.settings", fake)
    from navi.identity import load_identity

    return load_identity(tmp_path / "instance.json")


@pytest.fixture()
def client(peer_env):
    app = FastAPI()
    app.include_router(peer_routes.router)
    return TestClient(app)


def _headers(key: str = KEY) -> dict:
    return {"X-Swarm-Key": key}


def test_hello_is_open(client, peer_env):
    resp = client.get("/peer/hello")  # no key
    assert resp.status_code == 200
    body = resp.json()
    assert body["navi"] is True
    assert body["name"] == peer_env.name
    assert body["instance_id"] == peer_env.instance_id[:8]  # prefix only, not full uuid
    assert len(body["instance_id"]) == 8
    assert body["port"] == 8099


def test_status_requires_key(client):
    assert client.get("/peer/status").status_code == 401
    assert client.get("/peer/status", headers=_headers("wrong")).status_code == 403
    resp = client.get("/peer/status", headers=_headers())
    assert resp.status_code == 200
    body = resp.json()
    assert body["name"]
    assert "machine" in body
    assert body["hive"] == {"configured": False}  # no announcer in tests


def test_ask_requires_key(client, peer_env):
    payload = {"from_name": "amber-falcon", "from_instance_id": "x" * 32, "question": "hi"}
    assert client.post("/peer/ask", json=payload).status_code == 401
    assert client.post("/peer/ask", json=payload, headers=_headers("bad")).status_code == 403


def test_ask_loop_from_own_uuid_refused(client, peer_env, monkeypatch):
    payload = {"from_name": peer_env.name, "from_instance_id": peer_env.instance_id, "question": "echo?"}
    resp = client.post("/peer/ask", json=payload, headers=_headers())
    assert resp.status_code == 409


def test_ask_runs_agent_without_peer_tool(client, peer_env, monkeypatch):
    captured = {}

    class FakeAgent:
        async def run_ephemeral(self, user_message, profile_id, exclude_tools=None,
                                briefing=None, timeout_seconds=None, **kw):
            captured.update(
                message=user_message, profile=profile_id, exclude=exclude_tools,
                briefing=briefing, timeout=timeout_seconds,
            )
            return "the answer from the other side", True

    monkeypatch.setattr("navi.api.deps.get_agent", lambda: FakeAgent())
    payload = {"from_name": "amber-falcon", "from_instance_id": "y" * 32, "question": "what is your load?"}
    resp = client.post("/peer/ask", json=payload, headers=_headers())
    assert resp.status_code == 200
    body = resp.json()
    assert body["answer"] == "the answer from the other side"
    assert body["completed"] is True
    assert body["request_id"]
    # loop guard: answering agent has no peer tool, and the right profile
    assert captured["exclude"] == ["peer"]
    assert captured["profile"] == "server_admin"
    assert captured["message"] == "what is your load?"
    assert "amber-falcon" in captured["briefing"]


def test_ask_question_length_capped(client, peer_env):
    payload = {"from_name": "amber-falcon", "from_instance_id": "y" * 32, "question": "q" * 5000}
    assert client.post("/peer/ask", json=payload, headers=_headers()).status_code == 422


def test_previous_swarm_key_accepted(client, peer_env, tmp_path, monkeypatch):
    # rotation window: .swarm-key.previous still authenticates
    (tmp_path / ".swarm-key.previous").write_text("old-key")
    resp = client.get("/peer/status", headers={"X-Swarm-Key": "old-key"})
    assert resp.status_code == 200


def test_verify_swarm_key_rejects_garbage(tmp_path, monkeypatch):
    (tmp_path / ".swarm-key").write_text("real")
    fake = SimpleNamespace(swarm_key_file=str(tmp_path / ".swarm-key"))
    monkeypatch.setattr("navi.config.settings", fake)
    assert swarm.verify_swarm_key("real") is True
    assert swarm.verify_swarm_key("wrong") is False
    assert swarm.verify_swarm_key("") is False
    assert swarm.verify_swarm_key(None) is False