# SPDX-License-Identifier: Apache-2.0
"""Canonical JSON serialization and content hashing.

These are the foundation of NLAI's receipt identity model.
Do not change the canonical_json parameters without bumping
RECEIPT_SCHEMA_VERSION — stored hashes depend on this exact format.
"""

from __future__ import annotations

import hashlib
import json
from typing import Any


def canonical_json(obj: dict[str, Any]) -> bytes:
    """Deterministic JSON: sorted keys, compact separators, ASCII-safe.

    This is the canonical form used for all hashing. Identical to
    governor.gate_receipt.canonical_json — same inputs must produce
    same outputs, always.
    """
    return json.dumps(
        obj,
        sort_keys=True,
        separators=(",", ":"),
        ensure_ascii=True,
        allow_nan=False,
    ).encode("utf-8")


def content_hash(data: bytes, *, alg: str = "sha256") -> str:
    """Hash raw bytes, return hex digest."""
    if alg != "sha256":
        raise ValueError(f"Unsupported hash algorithm: {alg!r}")
    return hashlib.sha256(data).hexdigest()


def subject_hash(kind: str, content: bytes) -> str:
    """Hash subject with a kind tag to prevent cross-type collisions.

    kind: "text", "diff", "file_snapshot", etc.
    content: the raw bytes being checked.
    """
    return content_hash(kind.encode("utf-8") + b"\x00" + content)
