"""Serialization utilities for remote function invocation.

For MVP, uses JSON as the primary format with a pickle+base64 fallback
for types that JSON cannot handle natively.
"""

from __future__ import annotations

import base64
import json
import pickle
from typing import Any


def serialize(args: list[Any], kwargs: dict[str, Any]) -> str:
    """Serialize function arguments to a JSON string.

    Tries plain JSON first. If any value is not JSON-serializable,
    falls back to pickle + base64 encoding for the entire payload.
    """
    payload: dict[str, Any] = {"args": args, "kwargs": kwargs}

    try:
        return json.dumps(payload)
    except (TypeError, ValueError):
        # Fallback: pickle the entire payload and base64-encode it.
        pickled = pickle.dumps(payload, protocol=pickle.HIGHEST_PROTOCOL)
        encoded = base64.b64encode(pickled).decode("ascii")
        return json.dumps({"__velar_pickle__": True, "data": encoded})


def deserialize(data: str) -> tuple[list[Any], dict[str, Any]]:
    """Deserialize a JSON string back into (args, kwargs).

    Handles both plain JSON payloads and pickle+base64 payloads
    produced by :func:`serialize`.
    """
    payload = json.loads(data)

    if isinstance(payload, dict) and payload.get("__velar_pickle__"):
        decoded = base64.b64decode(payload["data"])
        payload = pickle.loads(decoded)  # noqa: S301 - trusted internal data

    args: list[Any] = payload.get("args", [])
    kwargs: dict[str, Any] = payload.get("kwargs", {})
    return args, kwargs
