"""Tests for PeerDrop Daemon protocol module."""

from peerdrop.daemon.protocol import (
    is_event,
    is_request,
    is_response,
    make_event,
    make_request,
    make_response,
    unpack_event,
    unpack_request,
    unpack_response,
)


class TestMakeRequest:
    def test_basic_request(self):
        data = make_request("discover_peers", request_id="abc")
        msg = unpack_request(data)
        assert msg["id"] == "abc"
        assert msg["action"] == "discover_peers"
        assert "params" not in msg

    def test_request_with_params(self):
        data = make_request("send_file", params={"file": "test.txt", "target": "Qm123"}, request_id="r1")
        msg = unpack_request(data)
        assert msg["id"] == "r1"
        assert msg["action"] == "send_file"
        assert msg["params"]["file"] == "test.txt"
        assert msg["params"]["target"] == "Qm123"

    def test_request_id_auto_generated(self):
        data = make_request("health")
        msg = unpack_request(data)
        assert isinstance(msg["id"], str)
        assert len(msg["id"]) > 0


class TestMakeResponse:
    def test_success_response(self):
        data = make_response("abc", ok=True, data={"peer_id": "Qm123"})
        msg = unpack_response(data)
        assert msg["id"] == "abc"
        assert msg["ok"] is True
        assert msg["data"]["peer_id"] == "Qm123"

    def test_error_response(self):
        data = make_response("abc", ok=False, error="Not found")
        msg = unpack_response(data)
        assert msg["id"] == "abc"
        assert msg["ok"] is False
        assert msg["error"] == "Not found"

    def test_response_no_data(self):
        data = make_response("abc", ok=True)
        msg = unpack_response(data)
        assert msg["id"] == "abc"
        assert msg["ok"] is True
        assert "data" not in msg


class TestMakeEvent:
    def test_basic_event(self):
        data = make_event("peer_discovered", data={"peer_id": "Qm123"})
        msg = unpack_event(data)
        assert msg["event"] == "peer_discovered"
        assert msg["data"]["peer_id"] == "Qm123"

    def test_event_no_data(self):
        data = make_event("daemon_ready")
        msg = unpack_event(data)
        assert msg["event"] == "daemon_ready"
        assert "data" not in msg


class TestMessageDetection:
    def test_is_request(self):
        assert is_request({"id": "1", "action": "health"}) is True
        assert is_request({"id": "1", "ok": True}) is False
        assert is_request({"event": "test"}) is False

    def test_is_response(self):
        assert is_response({"id": "1", "ok": True}) is True
        assert is_response({"id": "1", "ok": False, "error": "bad"}) is True
        assert is_response({"id": "1", "action": "health"}) is False

    def test_is_event(self):
        assert is_event({"event": "test", "data": {}}) is True
        assert is_event({"event": "test"}) is True
        assert is_event({"id": "1", "event": "test"}) is False
        assert is_event({"id": "1", "ok": True}) is False


class TestRoundTrip:
    def test_request_roundtrip(self):
        original = make_request("send_file", params={"file": "a.txt"}, request_id="xyz")
        unpacked = unpack_request(original)
        repacked = make_request(unpacked["action"], unpacked.get("params"), unpacked["id"])
        final = unpack_request(repacked)
        assert final == unpacked

    def test_response_roundtrip(self):
        original = make_response("xyz", ok=True, data={"count": 42})
        unpacked = unpack_response(original)
        repacked = make_response(unpacked["id"], unpacked["ok"], unpacked.get("data"))
        final = unpack_response(repacked)
        assert final == unpacked
