"""D — typed-canonical idempotency key.

The idempotency key is a TYPED canonical hash over a structured material object — NEVER a raw `||` string
concatenation (the Design Note forbids concatenation: two distinct field tuples could collide into one key).
The key is `DEFAULT_PROFILE.digest(canonical_bytes(material))` — the same RFC 8785 canonicalization + default
profile the rest of the Ledger uses, so it is deterministic and reproducible.
"""

from __future__ import annotations

from dataclasses import dataclass

from cl.canonical.hash_profile import DEFAULT_PROFILE
from cl.canonical.jcs import canonical_bytes


@dataclass(frozen=True)
class IdempotencyMaterial:
    schema_id: str
    schema_version: str
    producer_id: str
    action_intent_hash: str       # hex
    operation: str
    input_commitment: str         # hex

    def to_dict(self) -> dict:
        return {
            "schema_id": self.schema_id,
            "schema_version": self.schema_version,
            "producer_id": self.producer_id,
            "action_intent_hash": self.action_intent_hash,
            "operation": self.operation,
            "input_commitment": self.input_commitment,
        }


def idempotency_key(material: IdempotencyMaterial) -> bytes:
    """A typed canonical hash of `material` — RFC 8785 canonical bytes under DEFAULT_PROFILE (sha-256/32B).
    NEVER a raw `||` concatenation of the fields."""
    return DEFAULT_PROFILE.digest(canonical_bytes(material.to_dict()))
