"""Source registry — selection + enumeration of configured backends.

Built from settings at the composition root. Only sources that are configured
are registered (e.g. ``local`` appears only when ``LOCAL_MEDIA_IMPORT_PATH`` is
set), so enumeration reflects what the instance can actually use.
"""

from typing import cast

from app.core.config import Settings
from app.domain.errors import NotFoundError, ValidationError
from app.domain.ports import IndexableSource, SourceBackend
from app.domain.sources import SourceInfo
from app.infrastructure.sources.local_folder import LocalFolderSource


class SourceRegistry:
    def __init__(self, backends: list[SourceBackend]) -> None:
        self._by_name = {backend.name: backend for backend in backends}

    def get(self, name: str) -> SourceBackend:
        backend = self._by_name.get(name)
        if backend is None:
            raise NotFoundError(f"Source {name!r} is not configured.")
        return backend

    def indexable(self, name: str) -> IndexableSource:
        backend = self.get(name)
        if not hasattr(backend, "scan"):
            raise ValidationError(f"Source {name!r} cannot be indexed.")
        return cast(IndexableSource, backend)

    def infos(self) -> list[SourceInfo]:
        return [backend.info() for backend in self._by_name.values()]


def build_source_registry(settings: Settings) -> SourceRegistry:
    backends: list[SourceBackend] = []
    if settings.local_media_import_path is not None:
        backends.append(LocalFolderSource(settings.local_media_import_path))
    return SourceRegistry(backends)
