"""PeerDrop Daemon — IPC protocol message types.

Messages are serialized with msgpack over Unix sockets / TCP.
All requests have an "id" for correlation. Responses echo the id.
Events have no id (they are unsolicited pushes from daemon to client).
"""

from __future__ import annotations

import msgpack


# --- Request (client → daemon) ---

def make_request(action: str, params: dict | None = None, request_id: str = "") -> bytes:
    """Create a serialized request message."""
    import uuid as _uuid
    msg = {"id": request_id or _uuid.uuid4().hex[:8], "action": action}
    if params:
        msg["params"] = params
    return msgpack.packb(msg, use_bin_type=True)


def unpack_request(data: bytes) -> dict:
    """Deserialize a request message."""
    return msgpack.unpackb(data, raw=False)


# --- Response (daemon → client) ---

def make_response(request_id: str, ok: bool, data: dict | None = None, error: str = "") -> bytes:
    """Create a serialized response message."""
    msg: dict = {"id": request_id, "ok": ok}
    if data is not None:
        msg["data"] = data
    if error:
        msg["error"] = error
    return msgpack.packb(msg, use_bin_type=True)


def unpack_response(data: bytes) -> dict:
    """Deserialize a response message."""
    return msgpack.unpackb(data, raw=False)


# --- Event (daemon → client, no id) ---

def make_event(event_type: str, data: dict | None = None) -> bytes:
    """Create a serialized event message."""
    msg: dict = {"event": event_type}
    if data is not None:
        msg["data"] = data
    return msgpack.packb(msg, use_bin_type=True)


def unpack_event(data: bytes) -> dict:
    """Deserialize an event message."""
    return msgpack.unpackb(data, raw=False)


# --- Message type detection ---

def is_request(msg: dict) -> bool:
    """Check if a message is a request (has 'action' key)."""
    return "action" in msg


def is_response(msg: dict) -> bool:
    """Check if a message is a response (has 'ok' key)."""
    return "ok" in msg


def is_event(msg: dict) -> bool:
    """Check if a message is an event (has 'event' key, no 'id')."""
    return "event" in msg and "id" not in msg
