"""Deterministic canonical JSON helpers for AMCS-JCS-0.1."""

from __future__ import annotations

import json
from typing import Any


class CanonicalJSONError(TypeError):
    """Raised when an object cannot be canonicalized safely."""


def _reject_floats(obj: Any, *, path: str = "$") -> None:
    """Reject floats to avoid non-deterministic numeric representations."""
    if isinstance(obj, float):
        raise CanonicalJSONError(f"Floats are not allowed in canonical JSON (at {path})")

    if isinstance(obj, dict):
        for key, value in obj.items():
            _reject_floats(value, path=f"{path}.{key}")
        return

    if isinstance(obj, list):
        for index, value in enumerate(obj):
            _reject_floats(value, path=f"{path}[{index}]")


def canonical_dumps(obj: Any) -> str:
    """Serialize an object into deterministic canonical JSON text."""
    _reject_floats(obj)
    return json.dumps(
        obj,
        sort_keys=True,
        separators=(",", ":"),
        ensure_ascii=False,
        allow_nan=False,
    )


def canonical_bytes(obj: Any) -> bytes:
    """Serialize an object into deterministic canonical JSON UTF-8 bytes."""
    return canonical_dumps(obj).encode("utf-8")
