import importlib.util
import sys
import types
from pathlib import Path
from unittest.mock import MagicMock, patch


def _load_rtorrent_client_module():
    """
    使用轻量桩加载 rTorrent 客户端封装，避免测试依赖完整应用启动。
    """
    repo_root = Path(__file__).resolve().parents[1]

    app_module = types.ModuleType("app")
    app_module.__path__ = []
    log_module = types.ModuleType("app.log")

    class _Logger:
        """
        测试日志桩，仅提供被客户端封装调用的方法。
        """

        def info(self, *_args, **_kwargs):
            """
            忽略信息日志。
            """
            pass

        def warning(self, *_args, **_kwargs):
            """
            忽略警告日志。
            """
            pass

        def error(self, *_args, **_kwargs):
            """
            忽略错误日志。
            """
            pass

    log_module.logger = _Logger()
    app_module.log = log_module

    stub_modules = {
        "app": app_module,
        "app.log": log_module,
    }

    rtorrent_path = repo_root / "app" / "modules" / "rtorrent" / "rtorrent.py"
    rtorrent_spec = importlib.util.spec_from_file_location(
        "app.modules.rtorrent.rtorrent",
        rtorrent_path,
    )
    rtorrent_module = importlib.util.module_from_spec(rtorrent_spec)
    assert rtorrent_spec and rtorrent_spec.loader

    with patch.dict(sys.modules, stub_modules):
        rtorrent_spec.loader.exec_module(rtorrent_module)

    return rtorrent_module


rtorrent_module = _load_rtorrent_client_module()
Rtorrent = rtorrent_module.Rtorrent


def test_change_torrent_sets_per_task_speed_limits():
    """
    rTorrent 单任务限速应创建限速组并绑定到任务。
    """
    downloader = Rtorrent.__new__(Rtorrent)
    fake_proxy = MagicMock()
    downloader._proxy = fake_proxy

    assert downloader.change_torrent(
        hash_string="ABCDEF1234567890ABCDEF1234567890ABCDEF12",
        download_limit=1024,
        upload_limit=512,
    )

    fake_proxy.throttle.down.max.set.assert_called_once_with(
        "mp_abcdef1234567890",
        1024 * 1024,
    )
    fake_proxy.throttle.up.max.set.assert_called_once_with(
        "mp_abcdef1234567890",
        512 * 1024,
    )
    fake_proxy.d.throttle_name.set.assert_called_once_with(
        "ABCDEF1234567890ABCDEF1234567890ABCDEF12",
        "mp_abcdef1234567890",
    )


def test_change_torrent_allows_zero_limit_to_disable_limit():
    """
    rTorrent 单任务限速传 0 时应写入 0，表示关闭对应限速。
    """
    downloader = Rtorrent.__new__(Rtorrent)
    fake_proxy = MagicMock()
    downloader._proxy = fake_proxy

    assert downloader.change_torrent(
        hash_string="ABCDEF1234567890ABCDEF1234567890ABCDEF12",
        download_limit=0,
    )

    fake_proxy.throttle.down.max.set.assert_called_once_with(
        "mp_abcdef1234567890",
        0,
    )
    fake_proxy.throttle.up.max.set.assert_not_called()
    fake_proxy.d.throttle_name.set.assert_called_once_with(
        "ABCDEF1234567890ABCDEF1234567890ABCDEF12",
        "mp_abcdef1234567890",
    )


def test_set_torrent_location_updates_directory():
    """
    rTorrent 保存目录修改应调用 d.directory.set。
    """
    downloader = Rtorrent.__new__(Rtorrent)
    fake_proxy = MagicMock()
    downloader._proxy = fake_proxy

    assert downloader.set_torrent_location(
        hash_string="ABCDEF1234567890ABCDEF1234567890ABCDEF12",
        location="/downloads/new",
    )

    fake_proxy.d.directory.set.assert_called_once_with(
        "ABCDEF1234567890ABCDEF1234567890ABCDEF12",
        "/downloads/new",
    )
