import logging
from enum import Enum

from media_manager.config import AllEncompassingConfig
from media_manager.indexer.schemas import IndexerQueryResult
from media_manager.torrent.download_clients.abstractDownloadClient import (
    AbstractDownloadClient,
)
from media_manager.torrent.download_clients.qbittorrent import QbittorrentDownloadClient
from media_manager.torrent.download_clients.transmission import (
    TransmissionDownloadClient,
)
from media_manager.torrent.download_clients.sabnzbd import SabnzbdDownloadClient
from media_manager.torrent.schemas import Torrent, TorrentStatus

log = logging.getLogger(__name__)


class DownloadClientType(Enum):
    """Types of download clients supported"""

    TORRENT = "torrent"
    USENET = "usenet"


class DownloadManager:
    """
    Manages download clients and routes downloads to the appropriate client
    based on the content type (torrent vs usenet).
    Only one torrent client and one usenet client are active at a time.
    """

    def __init__(self):
        self._torrent_client: AbstractDownloadClient | None = None
        self._usenet_client: AbstractDownloadClient | None = None
        self.config = AllEncompassingConfig().torrents
        self._initialize_clients()

    def _initialize_clients(self) -> None:
        """Initialize and register the default download clients"""

        # Initialize torrent clients (prioritize qBittorrent, fallback to Transmission)
        if self.config.qbittorrent.enabled:
            try:
                self._torrent_client = QbittorrentDownloadClient()
                log.info(
                    "qBittorrent client initialized and set as active torrent client"
                )
            except Exception as e:
                log.error(f"Failed to initialize qBittorrent client: {e}")

        # If qBittorrent is not available or failed, try Transmission
        if self._torrent_client is None and self.config.transmission.enabled:
            try:
                self._torrent_client = TransmissionDownloadClient()
                log.info(
                    "Transmission client initialized and set as active torrent client"
                )
            except Exception as e:
                log.error(f"Failed to initialize Transmission client: {e}")

        # Initialize SABnzbd client for usenet
        if self.config.sabnzbd.enabled:
            try:
                self._usenet_client = SabnzbdDownloadClient()
                log.info("SABnzbd client initialized and set as active usenet client")
            except Exception as e:
                log.error(f"Failed to initialize SABnzbd client: {e}")

        active_clients = []
        if self._torrent_client:
            active_clients.append(f"torrent ({self._torrent_client.name})")
        if self._usenet_client:
            active_clients.append(f"usenet ({self._usenet_client.name})")

        log.info(
            f"Download manager initialized with active download clients: {', '.join(active_clients) if active_clients else 'none'}"
        )

    def _get_appropriate_client(
        self, indexer_result: IndexerQueryResult | Torrent
    ) -> AbstractDownloadClient:
        """
        Select the appropriate download client based on the indexer result

        :param indexer_result: The indexer query result to determine client type
        :return: The appropriate download client
        :raises RuntimeError: If no suitable client is available
        """
        # Use the usenet flag from the indexer result to determine the client type
        if indexer_result.usenet:
            if not self._usenet_client:
                raise RuntimeError("No usenet download client configured")
            log.info(
                f"Selected usenet client: {self._usenet_client.__class__.__name__}"
            )
            return self._usenet_client
        else:
            if not self._torrent_client:
                raise RuntimeError("No torrent download client configured")
            log.info(
                f"Selected torrent client: {self._torrent_client.__class__.__name__}"
            )
            return self._torrent_client

    def download(self, indexer_result: IndexerQueryResult) -> Torrent:
        """
        Download content using the appropriate client

        :param indexer_result: The indexer query result to download
        :return: The torrent object representing the download
        """
        log.info(f"Processing download request for: {indexer_result.title}")

        client = self._get_appropriate_client(indexer_result)
        return client.download_torrent(indexer_result)

    def remove_torrent(self, torrent: Torrent, delete_data: bool = False) -> None:
        """
        Remove a torrent using the appropriate client

        :param torrent: The torrent to remove
        :param delete_data: Whether to delete the downloaded data
        """
        log.info(f"Removing torrent: {torrent.title}")

        client = self._get_appropriate_client(torrent)
        client.remove_torrent(torrent, delete_data)

    def get_torrent_status(self, torrent: Torrent) -> TorrentStatus:
        """
        Get the status of a torrent using the appropriate client

        :param torrent: The torrent to get status for
        :return: The current status of the torrent
        """
        client = self._get_appropriate_client(torrent)
        return client.get_torrent_status(torrent)

    def pause_torrent(self, torrent: Torrent) -> None:
        """
        Pause a torrent using the appropriate client

        :param torrent: The torrent to pause
        """
        log.info(f"Pausing torrent: {torrent.title}")

        client = self._get_appropriate_client(torrent)
        client.pause_torrent(torrent)

    def resume_torrent(self, torrent: Torrent) -> None:
        """
        Resume a torrent using the appropriate client

        :param torrent: The torrent to resume
        """
        log.info(f"Resuming torrent: {torrent.title}")

        client = self._get_appropriate_client(torrent)
        client.resume_torrent(torrent)
