from __future__ import annotations

import base64

import scrape_forvo.api as api
from scrape_forvo.types import PlayItem


def _b64(s: str) -> str:
    return base64.b64encode(s.encode()).decode()


def _sample_html() -> str:
    mp3 = _b64("2/s/2s_egg_1.mp3")
    return (
        "var _AUDIO_HTTP_HOST = 'audio.forvo.com';"
        "<a onclick=\"Play(123,'x','%s','Label');return false;\">" % mp3
    )


def test_scrape_dry_run_returns_candidate(monkeypatch) -> None:
    fetched: dict[str, str] = {}

    def _fetch(url: str, session) -> str:
        fetched["url"] = url
        return _sample_html()

    monkeypatch.setattr(api, "make_session", lambda: object())
    monkeypatch.setattr(api, "fetch_html_requests", _fetch)
    monkeypatch.setattr(api, "iter_play_items", lambda html: iter((PlayItem("123", "egg", ("2/s/2s_egg_1.mp3",)),)))

    result = api.scrape("egg", dry_run=True, no_head=True, use_playwright=False)
    assert result.downloaded_count == 1
    assert len(result.candidates) == 1
    assert result.candidates[0].url == "https://audio.forvo.com/audios/mp3/2/s/2s_egg_1.mp3"
    assert fetched["url"] == "https://forvo.com/search/egg/no/"


def test_scrape_invalid_limit() -> None:
    try:
        api.scrape("egg", limit=-1)
    except ValueError as exc:
        assert "limit must be >= 0" in str(exc)
    else:
        raise AssertionError("Expected ValueError")


def test_scrape_filters_to_word_case_insensitive_trimmed(monkeypatch) -> None:
    monkeypatch.setattr(api, "make_session", lambda: object())
    monkeypatch.setattr(api, "fetch_html_requests", lambda url, session: _sample_html())
    monkeypatch.setattr(
        api,
        "iter_play_items",
        lambda html: iter(
            (
                PlayItem("1", "other", ("2/s/2s_other_1.mp3",)),
                PlayItem("2", "  EGG  ", ("2/s/2s_egg_1.mp3",)),
            )
        ),
    )

    result = api.scrape(" egg ", dry_run=True, no_head=True, use_playwright=False)
    assert result.downloaded_count == 1
    assert len(result.candidates) == 1
    assert result.candidates[0].play_id == "2"
