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 _open(js: JsPage, *, cards: str | None = None, project: str = "demo") -> None:
	js.route("board/list", body=[{"name": "Tasks"}, {"name": "Other"}])
	js.route("comments/list", body=[])
	js.route("board-ref-manifest", body=MANIFEST)
	js.route("tasks/list", body=[])
	js.route("tasks/update", status=200)
	html = board_shell(
		project=project,
		cards_todo=cards if cards is not None else card_html(ref="t1", title="Ship", description="see #abcd"),
	)
	js.set_html(html)
	js.load("board-popout.js")
	js.settle("__loaded['board-context.js'].refreshBoardRefManifest()")
	js.run("__loaded['board-popout.js'].showCardPopout(document.querySelector('.board-card'))")


def test_popout_edits_post_the_card_fields(js: JsPage) -> None:
	_open(js)
	assert "d-none" not in js.classes(".board-card-details")
	assert js.count(".board-card-popout-overlay") == 1
	assert js.count(".board-ref-commit") == 1
	js.click(".board-card-title")
	js.click(".board-card-title")
	js.set_prop(".board-card-title-edit", "value", "  ")
	js.dispatch(".board-card-title-edit", "keydown", key="Enter")
	assert js.text(".board-card-title") == "Untitled"
	js.click(".board-card-description-full")
	js.set_prop(".board-card-description-edit", "value", "updated")
	js.dispatch(".board-card-description-edit", "blur")
	assert js.text(".board-card-description-preview") == "updated"
	js.run("document.querySelector('.board-card-due-date').textContent = '2020-01-02 extra';")
	js.click(".board-card-due-date")
	assert js.prop(".board-card-due-date-edit", "value") == "2020-01-02"
	js.set_prop(".board-card-due-date-edit", "value", "")
	js.dispatch(".board-card-due-date-edit", "blur")
	assert js.text(".board-card-due-date") == "None"
	js.click(".board-card-status")
	js.run("document.querySelector('.board-card-status-edit option').textContent = 'In Progress';")
	js.dispatch(".board-card-status-edit", "change")
	assert js.text(".board-card-status") == "In Progress"
	assert js.attr(".board-card", "data-task-status") == "IN_PROGRESS"
	js.click(".board-card-priority")
	js.run("document.querySelector('.board-card-priority-edit option').textContent = 'High';")
	js.dispatch(".board-card-priority-edit", "change")
	assert js.text(".board-card-priority") == "High"
	js.click(".board-card-points")
	assert js.count(".board-card-points-edit option") == 9
	js.set_prop(".board-card-points-edit", "value", "5")
	js.dispatch(".board-card-points-edit", "change")
	assert js.text(".board-card-points") == "5"
	assert js.attr(".board-card", "data-task-points") == "5"
	js.click(".board-card-assignee")
	js.set_prop(".board-card-assignee-edit", "value", "Ada")
	js.dispatch(".board-card-assignee-edit", "keydown", key="Enter")
	assert js.text(".board-card-assignee-compact") == "Ada"
	js.run("document.querySelector('.board-card-tags').textContent = 'ui';")
	js.dispatch(".board-card-tags", "blur")
	body = posted_json(js, "tasks/update")
	assert body["title"] == "Untitled"
	assert body["description"] == "updated"
	assert body["status"] == "IN_PROGRESS"
	assert body["priority"] == "HIGH"
	assert body["points"] == 5
	assert body["assignee"] == "Ada"
	assert body["due_date"] is None
	assert body["tags"] == "ui"


def test_due_date_keeps_a_typed_value_and_rejects_junk(js: JsPage) -> None:
	_open(js)
	js.run("document.querySelector('.board-card-due-date').textContent = 'soon';")
	js.click(".board-card-due-date")
	assert js.prop(".board-card-due-date-edit", "value") == ""
	js.set_prop(".board-card-due-date-edit", "value", "2024-05-06")
	js.dispatch(".board-card-due-date-edit", "blur")
	assert posted_json(js, "tasks/update")["due_date"] == "2024-05-06"


def test_backdrop_restores_the_card_ahead_of_its_sibling(js: JsPage) -> None:
	_open(js, cards=card_html(ref="t1", title="A") + card_html(ref="t2", title="B"))
	assert js.count(".board-card-popout-overlay .board-card") == 1
	js.click(".board-card-popout-overlay")
	assert js.count(".board-card-popout-overlay") == 0
	titles = js.texts(".board-column-cards .board-card-title")
	assert titles == ["A", "B"]
	assert "d-none" in js.classes(".board-card-details")
	assert js.attr(".board-card", "draggable") == "true"


def test_closing_the_last_card_appends_it(js: JsPage) -> None:
	_open(js, cards=card_html(ref="t1", title="Only"))
	js.click(".board-card-popout-overlay")
	assert js.text(".board-column-cards .board-card-title") == "Only"


def test_delete_and_archive_ask_before_removing_the_card(js: JsPage) -> None:
	js.route("tasks/delete", status=200)
	js.route("tasks/archive", status=200)
	_open(js)
	js.run("__confirmYes = false;")
	js.click(".board-card-delete-btn")
	assert requested(js, "tasks/delete") is False
	assert "permanently" in js.value("__confirms")[0]
	js.run("__confirmYes = true;")
	js.click(".board-card-delete-btn")
	assert js.count(".board-card") == 0
	_open(js)
	js.route("tasks/delete", status=500)
	js.click(".board-card-delete-btn")
	assert js.count(".board-card") == 1
	js.click(".board-card-archive-btn")
	assert js.count(".board-card") == 0
	assert "Archive this task" in js.value("__confirms")[-1]


def test_archive_failure_leaves_the_card(js: JsPage) -> None:
	js.route("tasks/archive", error="offline")
	_open(js)
	js.click(".board-card-archive-btn")
	assert js.count(".board-card") == 1


def test_move_removes_the_card_or_shows_an_error(js: JsPage) -> None:
	js.route("tasks/move", status=200)
	_open(js)
	labels = js.texts(".board-card-move-select option")
	assert "Tasks" not in labels
	assert "Other" in labels
	js.dispatch(".board-card-move-select", "change")
	assert requested(js, "tasks/move") is False
	js.set_prop(".board-card-move-select", "value", "Other")
	js.dispatch(".board-card-move-select", "change")
	assert js.count(".board-card-popout-overlay") == 0
	assert any("target=Other" in str(item["url"]) for item in js.requests())
	js.route("tasks/move", status=401)
	_open(js)
	js.set_prop(".board-card-move-select", "value", "Other")
	js.dispatch(".board-card-move-select", "change")
	assert "Not authorized" in js.text(".board-task-error-hint")
	assert js.prop(".board-card-move-select", "value") == ""
	js.route("tasks/move", status=500)
	js.set_prop(".board-card-move-select", "value", "Other")
	js.dispatch(".board-card-move-select", "change")
	assert "Could not move task" in js.text(".board-task-error-hint")
	js.route("tasks/move", error="offline")
	js.set_prop(".board-card-move-select", "value", "Other")
	js.dispatch(".board-card-move-select", "change")
	assert "Could not move task" in js.text(".board-task-error-hint")


def test_actions_without_a_ref_or_project_are_not_bound(js: JsPage) -> None:
	_open(js, cards=card_html(title="Draft"), project="")
	js.set_location("http://127.0.0.1/")
	js.click(".board-card-delete-btn")
	assert js.value("__confirms") == []
	assert requested(js, "tasks/delete") is False


def test_assignee_cleared_to_none_posts_null(js: JsPage) -> None:
	_open(js)
	js.run("document.querySelector('.board-card-assignee').textContent = 'Ada';")
	js.click(".board-card-assignee")
	js.set_prop(".board-card-assignee-edit", "value", "")
	js.dispatch(".board-card-assignee-edit", "blur")
	assert js.text(".board-card-assignee") == "None"
	assert posted_json(js, "tasks/update")["assignee"] is None