import asyncio
import os
from pathlib import Path
from typing import Dict, List, Optional


class FileRepository:
    """
    Manage files from given base paths.

    Supports scanning and resolving files; ignores symlinks and skips
    inaccessible paths. Designed for extension with more file operations.
    """

    def __init__(self, base_paths: List[str | Path]) -> None:
        """
        Initialize repository with base paths.

        :param base_paths: List of directory or file paths to manage
        """
        self._base_paths: tuple[Path, ...] = tuple(Path(p) for p in base_paths)

    async def index(self) -> Dict[str, Path]:
        """
        Scan all base paths and return file index.

        :return: {file_name: absolute_path}
        """
        return await asyncio.to_thread(self._scanFiles)

    async def resolve(self, file_id: str) -> Optional[Path]:
        """
        Get full path for a file by name.

        :param file_id: File name to resolve
        :return: Path if found, else None
        """
        idx = await self.index()
        return idx.get(file_id)

    def _scanFiles(self) -> Dict[str, Path]:
        """
        Scan base paths for files.

        :return: {file_name: absolute_path}
        """
        index: Dict[str, Path] = {}
        for base in self._base_paths:
            try:
                if base.is_dir():
                    with os.scandir(base) as it:
                        for entry in it:
                            if entry.is_file(follow_symlinks=False):
                                index[entry.name] = Path(entry.path)
                elif base.is_file() and not base.is_symlink():
                    index[base.name] = base
            except (FileNotFoundError, PermissionError, OSError):
                continue
        return index
