from __future__ import annotations

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


def _routes(js: JsPage) -> None:
	js.route("board/list", body=[{"name": "Tasks", "task_count": 1}, {"name": "Sprint-2", "task_count": 0}])
	js.route("tasks/list", body=[])
	js.route("board-ref-manifest", body={"commits": [], "refs": []})
	js.route("/auth/status", body={"auth_enabled": False})


def test_init_waits_for_dom_content_loaded(js: JsPage) -> None:
	_routes(js)
	js.set_html(board_shell())
	js.run("document.readyState = 'loading';")
	js.load("board.js")
	assert js.value("__preloaded") == []
	js.run("document.readyState = 'complete';")
	js.run("document.dispatchEvent(new Event('DOMContentLoaded'))")
	assert len(js.value("__preloaded")) == 6


def test_selector_lists_boards_and_navigates(js: JsPage) -> None:
	_routes(js)
	js.set_html(board_shell())
	js.load("board.js")
	labels = js.value(
		"Array.from(document.querySelectorAll('#board-board-select option')).map(function(el){return el.textContent;})"
	)
	assert labels == ["Tasks (1)", "Sprint-2 (0)"]
	assert js.prop("#board-board-select", "value") == "Tasks"
	js.dispatch("#board-board-select", "change")
	assert js.value("__assigned") is None
	js.set_prop("#board-board-select", "value", "Sprint-2")
	js.dispatch("#board-board-select", "change")
	assert js.value("__assigned") == "/project/demo/board/?b=Sprint-2"


def test_unknown_current_board_is_inserted(js: JsPage) -> None:
	_routes(js)
	js.set_html(board_shell(board="Other"))
	js.load("board.js")
	assert js.prop("#board-board-select", "value") == "Other"
	assert js.text("#board-board-select option") == "Other"


def test_empty_or_failed_board_list_leaves_the_select(js: JsPage) -> None:
	js.route("board/list", body=[])
	js.route("tasks/list", body=[])
	js.route("board-ref-manifest", body={"commits": [], "refs": []})
	js.route("/auth/status", body={"auth_enabled": False})
	js.set_html(board_shell())
	js.load("board.js")
	assert js.count("#board-board-select option") == 0


def test_failed_board_list_leaves_the_select(js: JsPage) -> None:
	js.route("board/list", error="offline")
	js.route("tasks/list", body=[])
	js.route("board-ref-manifest", body={"commits": [], "refs": []})
	js.route("/auth/status", body={"auth_enabled": False})
	js.set_html(board_shell())
	js.load("board.js")
	assert js.count("#board-board-select option") == 0


def test_sprint_name_increments_and_the_form_can_be_cancelled(js: JsPage) -> None:
	_routes(js)
	js.route("board/list", body=[{"name": "Sprint-2"}, {"name": "notes"}, {"name": "Sprint-9"}])
	js.set_html(board_shell())
	js.load("board.js")
	js.click("#board-new-sprint-btn")
	assert "d-none" not in js.classes("#board-new-form")
	assert js.prop("#board-new-name", "value") == "Sprint-10"
	js.click("#board-new-cancel")
	assert "d-none" in js.classes("#board-new-form")
	js.click("#board-new-board-btn")
	assert js.prop("#board-new-name", "value") == ""


def test_create_board_navigates_or_shows_the_error(js: JsPage) -> None:
	_routes(js)
	js.route("board/create", status=200)
	js.set_html(board_shell())
	js.load("board.js")
	js.click("#board-new-board-btn")
	js.set_prop("#board-new-name", "value", "   ")
	js.dispatch("#board-new-form", "submit")
	assert requested(js, "board/create") is False
	js.set_prop("#board-new-name", "value", "My Board")
	js.dispatch("#board-new-form", "submit")
	assert js.value("__assigned") == "/project/demo/board/?b=My-Board"
	js.route("board/create", status=400, body={"detail": "taken"})
	js.set_prop("#board-new-name", "value", "Tasks")
	js.dispatch("#board-new-form", "submit")
	assert js.text("#board-new-error") == "taken"
	assert "d-none" not in js.classes("#board-new-error")
	js.route("board/create", status=400, json_error=True)
	js.dispatch("#board-new-form", "submit")
	assert js.text("#board-new-error") == "Could not create board."
	js.route("board/create", error="offline")
	js.dispatch("#board-new-form", "submit")
	assert js.text("#board-new-error") == "Could not create board."


def test_open_task_from_the_query_string(js: JsPage) -> None:
	_routes(js)
	js.route(
		"tasks/list",
		body=[{"ref": "refs/tags/tasks/task_abcd", "title": "Ship", "status": "TODO"}],
	)
	js.set_location("http://127.0.0.1/project/demo/board/?task=refs/tags/tasks/task_abcd")
	js.set_html(board_shell())
	js.load("board.js")
	assert js.count(".board-card-popout") == 0
	js.tick()
	assert "board-card-popout" in js.classes(".board-card")


def test_open_task_skips_a_card_that_is_already_open(js: JsPage) -> None:
	_routes(js)
	js.route("tasks/list", body=[{"ref": "t1", "title": "Ship", "status": "TODO"}])
	js.set_location("http://127.0.0.1/project/demo/board/?task=t1")
	js.set_html(board_shell())
	js.load("board.js")
	js.run("document.querySelector('.board-card').classList.add('board-card-popout')")
	js.tick()
	assert js.count(".board-card-popout-overlay") == 0


def test_missing_query_task_does_not_open_a_card(js: JsPage) -> None:
	_routes(js)
	js.set_html(board_shell())
	js.load("board.js")
	js.tick()
	assert js.count(".board-card-popout-overlay") == 0


def test_init_without_a_project_skips_the_network(js: JsPage) -> None:
	js.set_html('<div class="board-columns"></div><select id="board-board-select"></select>')
	js.set_location("http://127.0.0.1/")
	js.load("board.js")
	assert requested(js, "board/list") is False
	assert requested(js, "tasks/list") is False


def test_sprint_suggestion_starts_at_one_before_the_list_loads(js: JsPage) -> None:
	js.route("tasks/list", body=[])
	js.route("board-ref-manifest", body={"commits": [], "refs": []})
	js.route("/auth/status", body={"auth_enabled": False})
	js.set_html(board_shell())
	js.load("board.js")
	js.click("#board-new-sprint-btn")
	assert js.prop("#board-new-name", "value") == "Sprint-1"