from __future__ import annotations

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


def _bind(js: JsPage, html: str | None = None) -> None:
	js.set_html(html if html is not None else board_shell(cards_todo=card_html(ref="t1", title="A", points="1")))
	js.load("board-dnd.js")
	js.call("board-dnd.js", "bindBoardInteractions")


def test_binding_without_a_board_does_nothing(js: JsPage) -> None:
	js.set_html("<div></div>")
	js.load("board-dnd.js")
	js.call("board-dnd.js", "bindBoardInteractions")
	assert requested(js, "tasks/update") is False


def test_drop_on_another_column_saves_and_reorders(js: JsPage) -> None:
	js.route("tasks/update", status=200)
	js.route("tasks/list", body=[{"ref": "t1", "status": "IN_PROGRESS", "title": "A"}])
	_bind(js)
	js.dispatch(".board-card", "dragstart")
	assert "opacity-50" in js.classes(".board-card")
	js.dispatch('.board-column[data-status="IN_PROGRESS"]', "dragover")
	assert "border-primary" in js.classes('.board-column[data-status="IN_PROGRESS"]')
	js.dispatch('.board-column[data-status="IN_PROGRESS"]', "drop")
	assert js.count('.board-column[data-status="IN_PROGRESS"] .board-card') == 1
	assert js.attr(".board-card", "data-task-status") == "IN_PROGRESS"
	assert requested(js, "tasks/update") is True
	js.dispatch(".board-card", "dragend")
	assert "opacity-50" not in js.classes(".board-card")
	assert "border-primary" not in js.classes(".board-column")


def test_same_column_drop_does_not_save(js: JsPage) -> None:
	_bind(js)
	js.dispatch(".board-card", "dragstart")
	js.dispatch('.board-column[data-status="TODO"]', "drop")
	assert js.count('.board-column[data-status="TODO"] .board-card') == 1
	assert requested(js, "tasks/update") is False


def test_a_forbidden_move_puts_the_card_back(js: JsPage) -> None:
	js.route("tasks/update", status=403)
	html = board_shell(
		cards_todo=card_html(ref="t1", title="A") + card_html(ref="t2", title="B"),
	)
	_bind(js, html)
	js.dispatch('.board-card[data-task-ref="t1"]', "dragstart")
	js.dispatch('.board-column[data-status="IN_PROGRESS"]', "drop")
	assert js.count('.board-column[data-status="TODO"] .board-card') == 2
	assert "Not authorized" in js.text(".board-task-error-hint")
	js.route("tasks/update", status=500)
	js.dispatch('.board-card[data-task-ref="t1"]', "dragstart")
	js.dispatch('.board-column[data-status="IN_PROGRESS"]', "drop")
	assert "Could not save" in js.text(".board-task-error-hint")
	assert js.attr('.board-card[data-task-ref="t1"]', "data-task-status") == "TODO"


def test_a_card_without_a_ref_is_moved_back(js: JsPage) -> None:
	_bind(js, board_shell(cards_todo=card_html(title="A")))
	js.dispatch(".board-card", "dragstart")
	js.dispatch('.board-column[data-status="IN_PROGRESS"]', "drop")
	assert js.count('.board-column[data-status="TODO"] .board-card') == 1
	assert "Could not save" in js.text(".board-task-error-hint")


def test_drag_data_failures_still_move_the_dragged_card(js: JsPage) -> None:
	js.route("tasks/update", status=200)
	js.route("tasks/list", body=[{"ref": "t1", "status": "IN_PROGRESS"}])
	_bind(js)
	js.run("__failSetData = true;")
	js.dispatch(".board-card", "dragstart")
	assert "opacity-50" in js.classes(".board-card")
	js.run("__failGetData = true;")
	js.dispatch('.board-column[data-status="IN_PROGRESS"]', "drop")
	assert js.attr(".board-card", "data-task-status") == "IN_PROGRESS"


def test_click_opens_the_popout_unless_the_gesture_was_a_drag(js: JsPage) -> None:
	_bind(js)
	js.dispatch(".board-card", "dragstart")
	js.click(".board-card")
	assert js.count(".board-card-popout-overlay") == 0
	js.dispatch(".board-card", "dragend")
	js.tick()
	js.click(".board-card")
	assert js.count(".board-card-popout-overlay") == 1
	js.set_html(board_shell(cards_todo=card_html(ref="t1", title="A")))
	js.call("board-dnd.js", "bindBoardInteractions")
	js.run("document.querySelector('.board-card').classList.add('board-card-popout')")
	js.click(".board-card")
	assert js.count(".board-card-popout-overlay") == 0


def test_drop_without_a_card_or_a_list_is_ignored(js: JsPage) -> None:
	html = (
		'<div class="board-columns" data-project="demo" data-board="Tasks">'
		'<div class="board-column dropzone" data-status="TODO"></div>'
		'<div class="board-column dropzone" data-status="IN_PROGRESS"><div class="board-column-cards"></div></div>'
		"</div>"
	)
	_bind(js, html)
	js.dispatch('.board-column[data-status="IN_PROGRESS"]', "drop")
	js.dispatch('.board-column[data-status="TODO"]', "dragstart")
	js.dispatch('.board-column[data-status="TODO"]', "drop")
	assert requested(js, "tasks/update") is False


def test_dragover_outside_a_column_does_not_highlight(js: JsPage) -> None:
	_bind(js)
	js.dispatch(".board-column-cards", "dragover")
	assert "border-primary" not in js.classes(".board-column")