from __future__ import annotations

import base64

from pygitweb.static_tests.js_runtime import JsPage

_README = "# Demo\n\nHello **world**.\n\n[file](./a.md)\n\n[abs](https://example.com)\n\n[root](/x)\n\n[hash](#z)\n"
_B64 = base64.b64encode(_README.encode()).decode("ascii")


def _page(b64: str, *, blob_base: str | None = "/blob?f=", blob_dir: str = "docs") -> str:
    attrs = f'id="readme-container" data-readme-b64="{b64}"'
    if blob_base is not None:
        attrs += f' data-blob-base="{blob_base}" data-blob-dir="{blob_dir}"'
    return f'<div class="page"></div><div {attrs}></div>'


def test_missing_container_is_ignored(js: JsPage) -> None:
    js.set_html('<div class="page"></div>')
    js.load("readme-render.js")
    assert js.count(".readme-toc") == 0


def test_empty_payload_is_ignored(js: JsPage) -> None:
    js.set_html('<div class="page"></div><div id="readme-container"></div>')
    js.load("readme-render.js")
    assert js.count("h1") == 0


def test_render_builds_headings_links_and_a_hidden_toc(js: JsPage) -> None:
    js.set_location("http://127.0.0.1/readme")
    js.set_html(_page(_B64))
    js.load("readme-render.js")
    assert js.text("h1") == "Demo"
    assert js.count("strong") == 1
    file_href = js.attr('a[href*="blob"]', "href") or ""
    assert "docs%2Fa.md" in file_href
    assert js.attr('a[href="https://example.com"]', "href") == "https://example.com"
    assert js.attr('a[href="/x"]', "href") == "/x"
    assert js.count(".readme-section-anchor") == 1
    assert js.prop(".readme-toc-mount", "hidden") is True
    assert "readme-toc-active" in js.classes(".readme-toc-item")


def test_relative_links_stay_put_without_a_blob_base(js: JsPage) -> None:
    js.set_html(_page(_B64, blob_base=None))
    js.load("readme-render.js")
    assert js.attr('a[href="./a.md"]', "href") == "./a.md"


def test_invalid_base64_is_swallowed(js: JsPage) -> None:
    js.set_html(_page("!!!"))
    js.load("readme-render.js")
    assert js.count("h1") == 0


def test_section_anchor_copies_the_url(js: JsPage) -> None:
    js.set_location("http://127.0.0.1/readme?x=1")
    js.set_html(_page(_B64))
    js.load("readme-render.js")
    js.click(".readme-section-anchor")
    assert js.value("__copied") == js.value("location.origin") + "/readme?x=1#demo"


def test_section_anchor_sets_the_hash_without_clipboard(js: JsPage) -> None:
    js.set_location("http://127.0.0.1/readme")
    js.set_html(_page(_B64))
    js.load("readme-render.js")
    js.run("navigator.clipboard = null;")
    js.click(".readme-section-anchor")
    assert js.value("location.hash") == "#demo"


def test_toc_link_scrolls_and_updates_the_hash(js: JsPage) -> None:
    js.set_location("http://127.0.0.1/readme")
    js.set_html(_page(_B64))
    js.load("readme-render.js")
    js.click(".readme-toc-link")
    assert js.value("location.hash") == "#demo"
    assert js.value("__lastScrolled && __lastScrolled.id") == "demo"


def test_scroll_spy_shows_the_toc_and_marks_the_visible_heading(js: JsPage) -> None:
    js.set_html(_page(_B64))
    js.load("readme-render.js")
    js.run("document.getElementById('readme-container')._rectTop = -40;")
    js.run("document.querySelector('h1')._rectTop = -40;")
    js.run("window.scrollY = 0;")
    js.dispatch_window("scroll")
    js.dispatch_window("scroll")
    js.dispatch_window("resize")
    js.tick()
    assert js.prop(".readme-toc-mount", "hidden") is False
    assert "readme-toc-active" in js.classes(".readme-toc-item")


def test_generated_heading_ids_are_unique_and_protocol_relative_links_stay(js: JsPage) -> None:
    js.run(
        "var __real = showdown.Converter;"
        "showdown.Converter = function() { return { makeHtml: function() {"
        " return '<h1>Demo</h1><h1>Demo</h1><h2>!!!</h2><p>Hi</p>"
        '<a href="./a.md">f</a><a href="//cdn.example/a">c</a>\'; } }; };'
    )
    js.set_html(_page(_B64, blob_dir=""))
    js.load("readme-render.js")
    js.run("showdown.Converter = __real;")
    assert js.attr("h1", "id") == "demo"
    assert js.count("#demo-1") == 1
    assert js.count("#section") == 1
    assert "a.md" in (js.attr('a[href*="a.md"]', "href") or "")
    assert js.attr('a[href="//cdn.example/a"]', "href") == "//cdn.example/a"
    assert js.count(".page .readme-toc") == 1


def test_toc_is_not_mounted_without_a_page_column(js: JsPage) -> None:
    js.set_html(f'<div id="readme-container" data-readme-b64="{_B64}" data-blob-base="/b?f="></div>')
    js.load("readme-render.js")
    assert js.count("h1") == 1
    assert js.count(".readme-toc-mount") == 0