"""In-memory ArtifactRegistry. Persistence backends plug in later."""

from __future__ import annotations

import hashlib
import json
import time
import uuid
from dataclasses import dataclass, field
from typing import Any, Callable


Signer = Callable[[bytes], bytes]


@dataclass
class Artifact:
    id: str
    kind: str
    name: str
    data: dict[str, Any]
    content_hash: str
    created_at: float
    signature: bytes | None = None
    deleted: bool = False
    deletion_reason: str | None = None
    metadata: dict[str, Any] = field(default_factory=dict)


class ArtifactRegistry:
    """Content-addressed registry for named Axiom artifacts.

    Every artifact has:
      - a unique id (UUID4)
      - a content hash (SHA-256 of canonical JSON payload)
      - an optional signature (if a signer is provided at registry construction)
      - a tombstone-style deletion marker (deletes never destroy history)
    """

    def __init__(self, *, signer: Signer | None = None) -> None:
        self._store: dict[str, Artifact] = {}
        self._signer = signer

    def register(
        self,
        *,
        kind: str,
        name: str,
        data: dict[str, Any],
        metadata: dict[str, Any] | None = None,
    ) -> str:
        payload = {"kind": kind, "name": name, "data": data}
        canonical = json.dumps(payload, sort_keys=True).encode("utf-8")
        content_hash = hashlib.sha256(canonical).hexdigest()

        artifact = Artifact(
            id=uuid.uuid4().hex,
            kind=kind,
            name=name,
            data=data,
            content_hash=content_hash,
            created_at=time.time(),
            signature=self._signer(canonical) if self._signer else None,
            metadata=metadata or {},
        )
        self._store[artifact.id] = artifact
        return artifact.id

    def get(self, artifact_id: str) -> Artifact:
        return self._store[artifact_id]

    def list(self, *, kind: str | None = None, include_deleted: bool = False) -> list[Artifact]:
        out = []
        for a in self._store.values():
            if kind is not None and a.kind != kind:
                continue
            if a.deleted and not include_deleted:
                continue
            out.append(a)
        return out

    def delete(self, artifact_id: str, *, reason: str | None = None) -> None:
        a = self._store[artifact_id]
        a.deleted = True
        a.deletion_reason = reason
