from __future__ import annotations

from pygitweb.static_tests.js_runtime import JsPage


def _blob(js: JsPage, code: str, lines: str | None) -> None:
    href = "http://127.0.0.1/blob"
    if lines is not None:
        href += "?lines=" + lines
    js.set_location(href)
    js.set_html(f'<pre class="blob-content"><code>{code}</code></pre>')


def test_missing_code_element_is_ignored(js: JsPage) -> None:
    js.set_location("http://127.0.0.1/blob?lines=L1")
    js.set_html("<div></div>")
    js.load("blob-view.js")
    assert js.count("[data-line]") == 0


def test_no_lines_param_leaves_the_code_unwrapped(js: JsPage) -> None:
    js.run("globalThis.hljs = { highlightElement: function(code) { code.setAttribute('data-hl', '1'); } };")
    _blob(js, "print('hi')", None)
    js.load("blob-view.js")
    assert js.attr(".blob-content code", "data-hl") == "1"
    assert js.count("[data-line]") == 0


def test_a_full_line_range_selects_each_line_and_scrolls(js: JsPage) -> None:
    _blob(js, "alpha\nbeta\ngamma", "L1-L2")
    js.load("blob-view.js")
    assert "blob-line-selected" in js.classes('[data-line="1"]')
    assert "blob-line-selected" in js.classes('[data-line="2"]')
    assert "blob-line-selected" not in js.classes('[data-line="3"]')
    assert js.value("__lastScrolled && __lastScrolled.tagName") == "SPAN"


def test_a_character_range_wraps_a_selection_span(js: JsPage) -> None:
    _blob(js, "print('hi')", "L1C2-L1C5")
    js.load("blob-view.js")
    assert js.text(".blob-selection") == "rint"
    assert js.count(".blob-line-selected") == 0


def test_a_zero_width_range_does_not_wrap(js: JsPage) -> None:
    _blob(js, "print('hi')", "L1C5-L1C4")
    js.load("blob-view.js")
    assert js.count(".blob-selection") == 0
    assert js.count(".blob-line-selected") == 0


def test_a_missing_line_is_skipped(js: JsPage) -> None:
    _blob(js, "only", "L9")
    js.load("blob-view.js")
    assert js.count(".blob-line-selected") == 0
    assert js.value("__lastScrolled") is None


def test_highlight_elements_are_kept_inside_line_spans(js: JsPage) -> None:
    js.run(
        "globalThis.hljs = { highlightElement: function(code) {"
        " var text = code.textContent; code.textContent = '';"
        " var span = document.createElement('span'); span.className = 'hljs-built_in';"
        " span.textContent = text; code.appendChild(span); } };"
    )
    _blob(js, "print('hi')", "L1")
    js.load("blob-view.js")
    assert js.count('[data-line="1"] .hljs-built_in') == 1
    assert "blob-line-selected" in js.classes('[data-line="1"]')


def test_a_range_across_nodes_is_ignored_when_surround_fails(js: JsPage) -> None:
    _blob(js, "ab<span>XX</span>cd", "L1C1-L1C6")
    js.load("blob-view.js")
    assert js.count(".blob-selection") == 0
    assert js.count("[data-line]") == 1


def test_several_ranges_in_one_param_are_applied(js: JsPage) -> None:
    _blob(js, "one\ntwo", "L1,L2C1-L2C2")
    js.load("blob-view.js")
    assert "blob-line-selected" in js.classes('[data-line="1"]')
    assert js.text(".blob-selection") == "tw"