from __future__ import annotations

from pygitweb.static_tests.js_runtime import JsPage
from pygitweb.static_tests.pages import requested

_FORM = (
    '<input id="project_name">'
    '<input type="radio" name="project_source_type" value="empty" checked>'
    '<input type="radio" name="project_source_type" value="zip">'
    '<div id="tab-empty-repo"></div>'
    '<div id="tab-upload-zip" class="d-none"></div>'
    '<input id="pull_from_remote" value="git://example">'
    '<input id="repo_zip" value="old.zip">'
    '<div id="dropzone">'
    "<span data-dropzone-placeholder>drop</span>"
    '<span data-dropzone-filename class="d-none"></span>'
    "</div>"
)


def test_empty_document_skips_every_widget(js: JsPage) -> None:
    js.set_html("<div></div>")
    js.load("addproject.js")
    assert js.count("#project_name") == 0


def test_blank_name_clears_the_border(js: JsPage) -> None:
    js.set_html(_FORM)
    js.load("addproject.js")
    js.dispatch("#project_name", "blur")
    assert "border" not in js.classes("#project_name")
    assert requested(js, "projectnamevalid") is False


def test_blur_marks_an_accepted_name(js: JsPage) -> None:
    js.route("projectnamevalid", status=200)
    js.set_html(_FORM)
    js.load("addproject.js")
    js.set_prop("#project_name", "value", " demo ")
    js.dispatch("#project_name", "blur")
    assert "border-success" in js.classes("#project_name")
    assert any("name=demo" in str(item["url"]) for item in js.requests())


def test_blur_marks_a_rejected_name(js: JsPage) -> None:
    js.route("projectnamevalid", status=404)
    js.set_html(_FORM)
    js.load("addproject.js")
    js.set_prop("#project_name", "value", "taken")
    js.dispatch("#project_name", "blur")
    assert "border-danger" in js.classes("#project_name")


def test_name_check_clears_the_border_when_fetch_fails(js: JsPage) -> None:
    js.route("projectnamevalid", error="offline")
    js.set_html(_FORM)
    js.load("addproject.js")
    js.set_prop("#project_name", "value", "demo")
    js.dispatch("#project_name", "blur")
    assert "border" not in js.classes("#project_name")


def test_input_checks_the_name_after_the_debounce(js: JsPage) -> None:
    js.route("projectnamevalid", status=200)
    js.set_html(_FORM)
    js.load("addproject.js")
    js.set_prop("#project_name", "value", "demo")
    js.dispatch("#project_name", "input")
    assert requested(js, "projectnamevalid") is False
    js.tick()
    assert requested(js, "projectnamevalid") is True


def test_clearing_the_name_cancels_the_debounce(js: JsPage) -> None:
    js.route("projectnamevalid", status=200)
    js.set_html(_FORM)
    js.load("addproject.js")
    js.set_prop("#project_name", "value", "demo")
    js.dispatch("#project_name", "input")
    js.set_prop("#project_name", "value", "  ")
    js.dispatch("#project_name", "input")
    js.tick()
    assert requested(js, "projectnamevalid") is False
    assert "border" not in js.classes("#project_name")


def test_zip_source_hides_the_empty_tab_and_clears_the_remote(js: JsPage) -> None:
    js.set_html(_FORM)
    js.load("addproject.js")
    assert "d-none" not in js.classes("#tab-empty-repo")
    js.set_prop('input[value="empty"]', "checked", False)
    js.set_prop('input[value="zip"]', "checked", True)
    js.dispatch('input[value="zip"]', "change")
    assert "d-none" in js.classes("#tab-empty-repo")
    assert "d-none" not in js.classes("#tab-upload-zip")
    assert js.prop("#pull_from_remote", "value") == ""


def test_empty_source_clears_the_zip_input(js: JsPage) -> None:
    js.set_html(_FORM)
    js.load("addproject.js")
    js.set_prop('input[value="empty"]', "checked", False)
    js.set_prop('input[value="zip"]', "checked", True)
    js.dispatch('input[value="zip"]', "change")
    js.set_prop('input[value="zip"]', "checked", False)
    js.set_prop('input[value="empty"]', "checked", True)
    js.dispatch('input[value="empty"]', "change")
    assert js.prop("#repo_zip", "value") == ""
    assert "d-none" in js.classes("#tab-upload-zip")


def test_unchecked_radios_default_to_the_empty_source(js: JsPage) -> None:
    html = _FORM.replace(" checked", "", 1)
    js.set_html(html)
    js.load("addproject.js")
    assert "d-none" in js.classes("#tab-upload-zip")


def test_dropzone_click_clicks_the_file_input(js: JsPage) -> None:
    js.set_html(_FORM)
    js.load("addproject.js")
    js.run(
        "globalThis.__zipClicks = 0;"
        " document.getElementById('repo_zip').addEventListener('click', function() { __zipClicks++; });"
    )
    js.click("#dropzone")
    assert js.value("__zipClicks") == 1


def test_drag_highlights_the_dropzone_until_leave_or_drop(js: JsPage) -> None:
    js.set_html(_FORM)
    js.load("addproject.js")
    js.dispatch("#dropzone", "dragover")
    assert "border-primary" in js.classes("#dropzone")
    js.dispatch("#dropzone", "dragleave")
    assert "border-primary" not in js.classes("#dropzone")


def test_drop_accepts_only_a_zip_file(js: JsPage) -> None:
    js.set_html(_FORM)
    js.load("addproject.js")
    js.run(
        "var ev = new Event('drop', {bubbles:true, cancelable:true});"
        "ev.dataTransfer.files = [{name: 'notes.txt'}];"
        "document.getElementById('dropzone').dispatchEvent(ev);"
    )
    assert "Selected:" not in js.text("[data-dropzone-filename]")
    js.run(
        "var ev = new Event('drop', {bubbles:true, cancelable:true});"
        "ev.dataTransfer.files = [{name: 'Pkg.ZIP'}];"
        "document.getElementById('dropzone').dispatchEvent(ev);"
    )
    assert js.text("[data-dropzone-filename]") == "Selected: Pkg.ZIP"
    assert "d-none" in js.classes("[data-dropzone-placeholder]")
    assert "border-primary" not in js.classes("#dropzone")


def test_file_input_change_shows_and_clears_the_name(js: JsPage) -> None:
    js.set_html(_FORM)
    js.load("addproject.js")
    js.run("document.getElementById('repo_zip').files = [{name: 'a.zip'}];")
    js.dispatch("#repo_zip", "change")
    assert js.text("[data-dropzone-filename]") == "Selected: a.zip"
    js.run("document.getElementById('repo_zip').files = [];")
    js.dispatch("#repo_zip", "change")
    assert js.text("[data-dropzone-filename]") == ""
    assert "d-none" not in js.classes("[data-dropzone-placeholder]")