"""Serialize LangChain messages to JSON-friendly dicts.

Shared by server handler and desktop sidecar protocol.
"""
from __future__ import annotations
from typing import Any


def serialize_message(msg: Any) -> dict[str, Any]:
    """Convert a LangChain message object to a JSON-serializable dict.

    Produces enough detail for the React UI to render chat bubbles,
    tool call boxes, and tool results.
    """
    role = getattr(msg, "type", "unknown")
    content = getattr(msg, "content", "")
    # content can be a list of blocks (multimodal) — stringify for safety
    if isinstance(content, list):
        text_parts = []
        for block in content:
            if isinstance(block, str):
                text_parts.append(block)
            elif isinstance(block, dict) and block.get("type") == "text":
                text_parts.append(block.get("text", ""))
            elif isinstance(block, dict) and block.get("type") == "image_url":
                text_parts.append("[image]")
        content = "\n".join(text_parts) if text_parts else str(content)

    result: dict[str, Any] = {
        "role": role,
        "content": content,
        "id": getattr(msg, "id", None),
    }

    # AIMessage: include tool_calls so React can render ToolCallBox
    tool_calls = getattr(msg, "tool_calls", None)
    if tool_calls:
        result["tool_calls"] = [
            {"id": tc.get("id", ""), "name": tc.get("name", ""), "args": tc.get("args", {})}
            for tc in tool_calls
        ]

    # ToolMessage: include tool_call_id and tool name for pairing
    if role == "tool":
        result["tool_call_id"] = getattr(msg, "tool_call_id", None)
        result["name"] = getattr(msg, "name", None)
        result["status"] = getattr(msg, "status", "success")

    return result
