"""Download service for torrent files. Downloads to a given location."""

import asyncio
import logging
import pathlib

from mariner.clients.http import AsyncClientProtocol
from mariner.utils import path

log = logging.getLogger(__name__)


class Service:
    """Service to download torrent files asynchronously.

    Args:
        client: An async HTTP client for fetching files.
        download_path: Directory to save downloaded files to.

    """

    def __init__(
        self,
        client: AsyncClientProtocol,
        download_path: str | pathlib.Path | None = None,
    ) -> None:
        self._client = client
        self._download_path = path.exists_or_create(download_path or path.download())

    @property
    def download_path(self) -> pathlib.Path:
        """The directory where files are saved."""
        return self._download_path

    def download(self, files: list[tuple[str, str]]) -> list[pathlib.Path]:
        """Download files synchronously.

        Args:
            files: List of (url, filename) tuples.

        Returns:
            List of paths to downloaded files.

        """
        return asyncio.run(self._download_all(files))

    async def _download_all(self, files: list[tuple[str, str]]) -> list[pathlib.Path]:
        """Download all files concurrently.

        Args:
            files: List of (url, filename) tuples.

        Returns:
            List of paths to downloaded files.

        """
        tasks = [self.download_one(url, filename) for url, filename in files]
        return await asyncio.gather(*tasks)

    async def download_one(self, url: str, filename: str) -> pathlib.Path:
        """Download a single file.

        Args:
            url: URL to download from.
            filename: Name to save the file as.

        Returns:
            Path to the downloaded file.

        """
        dest = self._download_path / filename
        log.debug("Downloading %s to %s", url, dest)
        content = await self._client.get_bytes(url)
        dest.write_bytes(content)
        log.debug("Saved %s", dest)
        return dest
