from __future__ import annotations

from pygitweb.static_tests.js_runtime import JsPage
from pygitweb.static_tests.pages import MANIFEST, board_shell, card_html, posted_json, requested


def _board(js: JsPage, html: str | None = None) -> None:
	js.set_html(
		html if html is not None else board_shell(cards_todo=card_html(ref="refs/tags/tasks/task_abcd", title="Ship"))
	)
	js.load("board-context.js")


def test_task_ids_drop_the_prefix_and_shorten(js: JsPage) -> None:
	_board(js, "<div></div>")
	assert js.call("board-context.js", "taskDisplayId", "") == ""
	assert js.call("board-context.js", "taskDisplayId", "refs/tags/tasks/task_abcd") == "abcd"
	assert js.call("board-context.js", "taskDisplayId", "refs/tags/tasks/custom") == "custom"
	assert js.call("board-context.js", "taskDisplayIdShort", "") == ""
	assert js.call("board-context.js", "taskDisplayIdShort", "ab") == "ab"
	assert js.call("board-context.js", "taskDisplayIdShort", "abcdef") == "cdef"


def test_context_comes_from_the_dataset_or_the_url(js: JsPage) -> None:
	_board(js)
	assert js.call("board-context.js", "getBoardContext") == {"project": "demo", "board": "Tasks"}
	js.set_html('<div class="board-columns"></div>')
	js.set_location("http://127.0.0.1/project/demo/board/?b=Sprint")
	js.load("board-context.js")
	assert js.call("board-context.js", "getBoardContext") == {"project": "demo", "board": "Sprint"}
	js.set_location("http://127.0.0.1/project/demo/board")
	assert js.call("board-context.js", "getBoardContext")["board"] == "Tasks"


def test_find_card_matches_the_task_ref(js: JsPage) -> None:
	_board(js)
	assert js.call("board-context.js", "findBoardCardByTaskRef", "") is None
	assert js.value("__loaded['board-context.js'].findBoardCardByTaskRef('missing')") is None
	assert js.value("__loaded['board-context.js'].findBoardCardByTaskRef('refs/tags/tasks/task_abcd') !== null") is True


def test_title_tooltip_uses_the_id_and_falls_back_to_untitled(js: JsPage) -> None:
	js.set_html('<div class="board-card"></div>')
	js.load("board-context.js")
	js.run("__loaded['board-context.js'].syncCardTitleLineTooltip(document.querySelector('.board-card'))")
	js.set_html(board_shell(cards_todo=card_html(title="  ")))
	js.run("__loaded['board-context.js'].syncCardTitleLineTooltip(document.querySelector('.board-card'))")
	assert js.attr(".board-card-title-line", "title") == "Untitled"
	js.set_html(board_shell(cards_todo=card_html(ref="refs/tags/tasks/task_abcd", title="Ship")))
	js.run(
		"__loaded['board-context.js'].setCardTaskRefDisplay("
		"document.querySelector('.board-card'), 'refs/tags/tasks/task_abcd', null)"
	)
	assert js.text(".board-card-task-id") == "abcd"
	assert js.text(".board-card-task-ref") == "refs/tags/tasks/task_abcd"
	assert js.attr(".board-card-title-line", "title") == "abcd: Ship"


def test_title_line_without_a_title_element_uses_untitled(js: JsPage) -> None:
	js.set_html(
		'<div class="board-card" data-task-ref="refs/tags/tasks/task_abcd">'
		'<div class="board-card-title-line"></div>'
		'<span class="board-card-task-id"></span>'
		'<div class="board-card-task-ref">old</div></div>'
	)
	js.load("board-context.js")
	js.run("__loaded['board-context.js'].syncCardTitleLineTooltip(document.querySelector('.board-card'))")
	assert js.attr(".board-card-title-line", "title") == "abcd: Untitled"
	js.run("__loaded['board-context.js'].setCardTaskRefDisplay(document.querySelector('.board-card'), '', 'abcd')")
	assert js.text(".board-card-task-ref") == ""


def test_error_hint_replaces_itself_and_expires(js: JsPage) -> None:
	_board(js, "<div></div>")
	js.call("board-context.js", "showBoardError", "nope")
	assert js.count(".board-task-error-hint") == 0
	_board(js)
	js.call("board-context.js", "showBoardError", "first")
	js.call("board-context.js", "showBoardError", "second")
	assert js.count(".board-task-error-hint") == 1
	assert js.text(".board-task-error-hint") == "second"
	js.tick()
	assert js.count(".board-task-error-hint") == 0


def test_column_badge_sums_points(js: JsPage) -> None:
	html = board_shell(
		cards_todo=card_html(ref="a", points="2") + card_html(ref="b", points="3") + card_html(ref="c", points=""),
	)
	_board(js, html)
	js.run("__loaded['board-context.js'].updateColumnBadge(null)")
	js.run("__loaded['board-context.js'].updateColumnBadge(document.querySelector('.board-column'))")
	assert js.text(".board-column-task-count") == "3"
	assert js.text(".board-column-points-total") == "5 pts"
	js.set_html('<div class="board-column"></div>')
	js.load("board-context.js")
	js.run("__loaded['board-context.js'].updateColumnBadge(document.querySelector('.board-column'))")
	assert js.count(".board-column-task-count") == 0


def test_field_update_posts_json_and_reports_failures(js: JsPage) -> None:
	_board(js, "<div></div>")
	assert js.settle("__loaded['board-context.js'].pushTaskFieldUpdate(null, {})") == {"ok": False, "status": 0}
	_board(js)
	card = "document.querySelector('.board-card')"
	js.route("tasks/update", error="offline")
	assert js.settle(f"__loaded['board-context.js'].pushTaskFieldUpdate({card}, {{a:1}})") == {
		"ok": False,
		"status": 0,
	}
	js.route("tasks/update", status=200)
	assert js.settle(f"__loaded['board-context.js'].pushTaskFieldUpdate({card}, {{title:'Ship'}})") == {
		"ok": True,
		"status": 200,
	}
	assert posted_json(js, "tasks/update")["title"] == "Ship"
	js.route("tasks/update", status=404)
	assert js.settle(f"__loaded['board-context.js'].pushTaskFieldUpdate({card}, {{}})")["status"] == 404
	js.route("tasks/update", error="offline")
	assert js.settle(f"__loaded['board-context.js'].pushTaskFieldUpdate({card}, {{}})") == {"ok": False, "status": 0}
	js.set_html('<div class="board-columns"><div class="board-card" data-task-ref="t"></div></div>')
	js.load("board-context.js")
	assert js.settle("__loaded['board-context.js'].pushTaskFieldUpdate(document.querySelector('.board-card'), {})") == {
		"ok": False,
		"status": 0,
	}


def test_refresh_stores_the_manifest_or_an_empty_one(js: JsPage) -> None:
	_board(js, '<div class="board-columns"></div>')
	js.set_location("http://127.0.0.1/")
	assert js.settle("__loaded['board-context.js'].refreshBoardRefManifest()") is None
	js.route("board-ref-manifest", body=MANIFEST)
	_board(js)
	got = js.settle("__loaded['board-context.js'].refreshBoardRefManifest()")
	assert got["commits"][0]["insert"] == "abcd"
	assert js.call("board-context.js", "getBoardRefManifest")["refs"][0]["insert"] == "main"
	js.route("board-ref-manifest", status=500)
	empty = js.settle("__loaded['board-context.js'].refreshBoardRefManifest()")
	assert empty == {"commits": [], "refs": []}
	js.route("board-ref-manifest", error="offline")
	assert js.settle("__loaded['board-context.js'].refreshBoardRefManifest()") == {"commits": [], "refs": []}
	assert requested(js, "board-ref-manifest") is True