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]")