"""File storage abstraction — local disk first, S3-ready interface."""

import os
import shutil
from abc import ABC, abstractmethod
from pathlib import Path

from app.config import STORAGE_BACKEND, STORAGE_LOCAL_PATH


class StorageBackend(ABC):
    @abstractmethod
    def save(self, item_id: str, asset_type: str, filename: str, data: bytes) -> str:
        """Save file, return relative storage path."""
        ...

    @abstractmethod
    def read(self, path: str) -> bytes:
        ...

    @abstractmethod
    def delete(self, path: str) -> None:
        ...

    @abstractmethod
    def exists(self, path: str) -> bool:
        ...

    @abstractmethod
    def url(self, path: str) -> str:
        """Return a URL or local path for serving."""
        ...


class LocalStorage(StorageBackend):
    def __init__(self, base_path: str):
        self.base = Path(base_path)
        self.base.mkdir(parents=True, exist_ok=True)

    def _full_path(self, path: str) -> Path:
        return self.base / path

    def save(self, item_id: str, asset_type: str, filename: str, data: bytes) -> str:
        rel = f"{item_id}/{asset_type}/{filename}"
        full = self._full_path(rel)
        full.parent.mkdir(parents=True, exist_ok=True)
        full.write_bytes(data)
        return rel

    def read(self, path: str) -> bytes:
        return self._full_path(path).read_bytes()

    def delete(self, path: str) -> None:
        full = self._full_path(path)
        if full.exists():
            full.unlink()
        # Clean empty parent dirs
        parent = full.parent
        while parent != self.base:
            try:
                parent.rmdir()
                parent = parent.parent
            except OSError:
                break

    def exists(self, path: str) -> bool:
        return self._full_path(path).exists()

    def url(self, path: str) -> str:
        return f"/storage/{path}"


# Future: S3Storage class implementing the same interface

def _create_storage() -> StorageBackend:
    if STORAGE_BACKEND == "local":
        return LocalStorage(STORAGE_LOCAL_PATH)
    raise ValueError(f"Unknown storage backend: {STORAGE_BACKEND}")


storage = _create_storage()
