from pathlib import Path

from zbt.core.config import Settings
from zbt.domains.service_request.storage import StoredMaterial


class LocalMaterialStorage:
    """在本地受控目录保存服务材料，文件不通过静态目录公开。"""

    def __init__(self, settings: Settings) -> None:
        self._root = settings.service_material_storage_path.resolve()
        self._root.mkdir(parents=True, exist_ok=True)

    def save(self, recognition_id: str, content: bytes) -> None:
        target = self._path(recognition_id)
        temporary = target.with_suffix(".uploading")
        temporary.write_bytes(content)
        temporary.replace(target)

    def load(self, recognition_id: str) -> StoredMaterial | None:
        target = self._path(recognition_id)
        if not target.is_file():
            return None
        return StoredMaterial(target.read_bytes())

    def exists(self, recognition_id: str) -> bool:
        return self._path(recognition_id).is_file()

    def delete(self, recognition_id: str) -> None:
        self._path(recognition_id).unlink(missing_ok=True)

    def _path(self, recognition_id: str) -> Path:
        if not 16 <= len(recognition_id) <= 64 or not recognition_id.isalnum():
            raise ValueError("材料识别 ID 格式无效")
        target = (self._root / f"{recognition_id}.material").resolve()
        if target.parent != self._root:
            raise ValueError("材料存储路径无效")
        return target
