"""Content-addressed artifact store (CAS).

Stores artifacts by their SHA-256 digest in a flat directory structure.
"""

from __future__ import annotations

import hashlib
import shutil
from pathlib import Path


class ArtifactStore:
    """Content-addressed store for binary artifacts.

    Artifacts are stored at ``<root>/<digest_hex>`` where ``digest_hex``
    is the lowercase hex SHA-256 of the file contents.
    """

    def __init__(self, root: Path) -> None:
        self.root = root
        self.root.mkdir(parents=True, exist_ok=True)

    def put_bytes(self, data: bytes) -> tuple[str, Path]:
        """Store raw bytes and return (digest, path).

        Args:
            data: Raw bytes to store.

        Returns:
            Tuple of (sha256 hex digest, path to stored file).
        """
        digest = hashlib.sha256(data).hexdigest()
        dest = self.root / digest
        if not dest.exists():
            dest.write_bytes(data)
        return digest, dest

    def put_file(self, source: Path) -> tuple[str, Path]:
        """Store a file by copying it into the CAS.

        Args:
            source: Path to the file to store.

        Returns:
            Tuple of (sha256 hex digest, path to stored file).
        """
        data = source.read_bytes()
        digest = hashlib.sha256(data).hexdigest()
        dest = self.root / digest
        if not dest.exists():
            shutil.copy2(source, dest)
        return digest, dest

    def get_path(self, digest: str) -> Path:
        """Return the path to a stored artifact by digest.

        Args:
            digest: SHA-256 hex digest.

        Returns:
            Path to the artifact file.

        Raises:
            FileNotFoundError: If no artifact with this digest exists.
        """
        p = self.root / digest
        if not p.exists():
            raise FileNotFoundError(f"Artifact not found: {digest}")
        return p

    def contains(self, digest: str) -> bool:
        """Check if an artifact with the given digest exists."""
        return (self.root / digest).exists()
