from __future__ import annotations

import asyncio

from thread_downloader import DownloadConfig, Downloader, RetryPolicy, DownloadTask

from conftest import run_test_server


def test_range_supported_uses_multi_thread(tmp_path, sample_data: bytes) -> None:
    downloader = Downloader(DownloadConfig(workers=4))
    target = tmp_path / "range.bin"

    with run_test_server(support_range=True, data=sample_data) as (url, state):
        task = DownloadTask(url, str(target))
        result = asyncio.run(downloader.download(task))

    assert result.used_multi_thread is True
    assert result.range_supported is True
    assert state.multi_range_requests > 0
    assert target.read_bytes() == sample_data


def test_range_not_supported_falls_back_to_single_thread(tmp_path, sample_data: bytes) -> None:
    downloader = Downloader(DownloadConfig(workers=4))
    target = tmp_path / "single.bin"

    with run_test_server(support_range=False, data=sample_data) as (url, state):
        task = DownloadTask(url, str(target))
        result = asyncio.run(downloader.download(task))

    assert result.used_multi_thread is False
    assert result.range_supported is False
    assert state.multi_range_requests == 0
    assert target.read_bytes() == sample_data


def test_retry_handles_transient_server_failure(tmp_path, sample_data: bytes) -> None:
    retry_policy = RetryPolicy(max_attempts=2, backoff_seconds=0.01, max_backoff_seconds=0.02)
    downloader = Downloader(DownloadConfig(workers=2, retry_policy=retry_policy))
    target = tmp_path / "retry.bin"

    with run_test_server(support_range=False, data=sample_data, fail_first=True) as (url, _state):
        task = DownloadTask(url, str(target))
        result = asyncio.run(downloader.download(task))

    assert result.bytes_written == len(sample_data)
    assert target.read_bytes() == sample_data
