import httpx
import respx

from mcsci_hub.clients.scihub import SciHubClient
from tests.conftest import SAMPLE_SCIHUB_HTML


@respx.mock
async def test_find_pdf_url_iframe(scihub_client: SciHubClient):
    respx.get("https://sci-hub.test/10.1038/nature12373").mock(
        return_value=httpx.Response(200, text=SAMPLE_SCIHUB_HTML)
    )
    url = await scihub_client.find_pdf_url("10.1038/nature12373")
    assert url is not None
    assert url == "https://sci-hub.test/downloads/2017/nature12373.pdf"


@respx.mock
async def test_find_pdf_url_embed():
    client = httpx.AsyncClient()
    scihub = SciHubClient(client, mirrors=["mirror.test"])
    html = '<html><embed type="application/pdf" src="//mirror.test/paper.pdf"></html>'
    respx.get("https://mirror.test/10.1234/test").mock(
        return_value=httpx.Response(200, text=html)
    )
    url = await scihub.find_pdf_url("10.1234/test")
    assert url == "https://mirror.test/paper.pdf"


@respx.mock
async def test_find_pdf_url_direct_link():
    client = httpx.AsyncClient()
    scihub = SciHubClient(client, mirrors=["mirror.test"])
    html = '<html><a href="https://cdn.test/paper.pdf">Download</a></html>'
    respx.get("https://mirror.test/10.1234/test").mock(
        return_value=httpx.Response(200, text=html)
    )
    url = await scihub.find_pdf_url("10.1234/test")
    assert url == "https://cdn.test/paper.pdf"


@respx.mock
async def test_find_pdf_url_not_found(scihub_client: SciHubClient):
    respx.get("https://sci-hub.test/10.0000/nope").mock(
        return_value=httpx.Response(200, text="<html><body>Not found</body></html>")
    )
    url = await scihub_client.find_pdf_url("10.0000/nope")
    assert url is None


@respx.mock
async def test_find_pdf_url_server_error(scihub_client: SciHubClient):
    respx.get("https://sci-hub.test/10.0000/err").mock(
        return_value=httpx.Response(500)
    )
    url = await scihub_client.find_pdf_url("10.0000/err")
    assert url is None


@respx.mock
async def test_check_mirror_reachable(scihub_client: SciHubClient):
    respx.get("https://sci-hub.test").mock(return_value=httpx.Response(200))
    assert await scihub_client.check_mirror("sci-hub.test") is True


@respx.mock
async def test_check_mirror_unreachable(scihub_client: SciHubClient):
    respx.get("https://sci-hub.test").mock(return_value=httpx.Response(500))
    assert await scihub_client.check_mirror("sci-hub.test") is False


def test_normalize_url():
    assert SciHubClient._normalize_url("//example.com/a.pdf") == "https://example.com/a.pdf"
    assert SciHubClient._normalize_url("https://example.com/a.pdf") == "https://example.com/a.pdf"


@respx.mock
async def test_download_pdf(scihub_client: SciHubClient, tmp_path):
    pdf_content = b"%PDF-1.4 fake pdf content here"
    respx.get("https://cdn.test/paper.pdf").mock(
        return_value=httpx.Response(
            200,
            content=pdf_content,
            headers={"content-type": "application/pdf"},
        )
    )
    save_path = tmp_path / "test.pdf"
    success = await scihub_client.download_pdf("https://cdn.test/paper.pdf", save_path)
    assert success is True
    assert save_path.exists()
    assert save_path.read_bytes() == pdf_content
