"""Content-addressed object store (hash -> bytes)."""

from __future__ import annotations

import os
from dataclasses import dataclass
from pathlib import Path
from typing import Optional


@dataclass(frozen=True)
class ObjectStore:
    root: Path

    def objects_dir(self) -> Path:
        return self.root / "objects"

    def _path_for(self, obj_hash: str) -> Path:
        prefix = obj_hash[:2]
        return self.objects_dir() / prefix / obj_hash

    def init(self) -> None:
        self.objects_dir().mkdir(parents=True, exist_ok=True)

    def has(self, obj_hash: str) -> bool:
        return self._path_for(obj_hash).exists()

    def get(self, obj_hash: str) -> Optional[bytes]:
        path = self._path_for(obj_hash)
        if not path.exists():
            return None
        return path.read_bytes()

    def put(self, obj_hash: str, data: bytes) -> None:
        path = self._path_for(obj_hash)
        path.parent.mkdir(parents=True, exist_ok=True)
        # Write atomically to avoid partial files.
        tmp_path = path.with_suffix(".tmp")
        tmp_path.write_bytes(data)
        os.replace(tmp_path, path)
