from __future__ import annotations

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


def _card(js: JsPage) -> None:
	js.set_html(board_shell(cards_todo=card_html(ref="refs/tags/tasks/task_abcd", title="Ship")))
	js.load("board-comments.js")


def test_comment_labels_and_counts(js: JsPage) -> None:
	_card(js)
	assert js.call("board-comments.js", "commentCountLabel", 0) == "0 comments"
	assert js.call("board-comments.js", "commentCountLabel", 1) == "1 comment"
	assert js.call("board-comments.js", "commentCountLabel", 2) == "2 comments"
	js.run("__loaded['board-comments.js'].updateCardCommentCount(document.querySelector('.board-card'), 1)")
	assert js.text(".board-card-comments-count-meta") == "1 comment"
	js.set_html("<div class='board-card'></div>")
	js.run("__loaded['board-comments.js'].updateCardCommentCount(document.querySelector('.board-card'), 3)")
	assert js.count(".board-card-comments-count-meta") == 0


def test_comments_render_avatars_markdown_and_initials(js: JsPage) -> None:
	js.route(
		"comments/list",
		body=[
			{"author": "Ada Lovelace", "content": "**hi**", "gravatar_url": "http://img/a"},
			{"author": "sam", "content": "yo"},
			{"content": ""},
		],
	)
	_card(js)
	comments = js.settle("__loaded['board-comments.js'].loadCommentsForCard(document.querySelector('.board-card'))")
	assert len(comments) == 3
	assert js.text(".board-card-comments-count-meta") == "3 comments"
	assert js.count(".board-card-comment-item") == 3
	assert js.count("#md strong") == 0
	assert js.count(".board-card-comment-content strong") == 1
	assert js.prop(".board-card-comment-avatar img", "src") == "http://img/a"
	js.run("document.querySelector('.board-card-comment-avatar img').onerror()")
	assert js.text(".board-card-comment-avatar-fallback") == "AL"
	assert js.text(".board-card-comment-author") == "Ada Lovelace"
	fallbacks = js.texts(".board-card-comment-avatar-fallback")
	assert fallbacks == ["AL", "S", "?"]


def test_comment_load_tolerates_empty_and_failed_responses(js: JsPage) -> None:
	_card(js)
	js.route("comments/list", status=404)
	assert js.settle("__loaded['board-comments.js'].loadCommentsForCard(document.querySelector('.board-card'))") == []
	js.route("comments/list", status=500)
	assert js.settle("__loaded['board-comments.js'].loadCommentsForCard(document.querySelector('.board-card'))") == []
	js.route("comments/list", body={"nope": True})
	assert js.settle("__loaded['board-comments.js'].loadCommentsForCard(document.querySelector('.board-card'))") == []
	js.route("comments/list", error="offline")
	assert js.settle("__loaded['board-comments.js'].loadCommentsForCard(document.querySelector('.board-card'))") == []
	js.set_html('<div class="board-columns" data-project="demo"><div class="board-card"></div></div>')
	assert js.settle("__loaded['board-comments.js'].loadCommentsForCard(document.querySelector('.board-card'))") is None
	js.set_html('<div class="board-columns"><div class="board-card" data-task-ref="t"></div></div>')
	js.set_location("http://127.0.0.1/")
	assert js.settle("__loaded['board-comments.js'].loadCommentsForCard(document.querySelector('.board-card'))") is None


def test_comment_form_hides_until_a_user_is_signed_in(js: JsPage) -> None:
	js.route("/auth/status", body={"auth_enabled": True})
	_card(js)
	js.settle("__loaded['board-comments.js'].loadBoardAuthStatus()")
	js.run("__loaded['board-comments.js'].setupCommentForm(document.querySelector('.board-card'))")
	assert "d-none" in js.classes(".board-card-comment-form")
	assert "d-none" not in js.classes(".board-card-comment-signin-hint")
	js.route("/auth/status", body={"auth_enabled": True, "username": "ada"})
	js.settle("__loaded['board-comments.js'].loadBoardAuthStatus()")
	js.set_html(board_shell(cards_todo=card_html(ref="refs/tags/tasks/task_abcd")))
	js.run("__loaded['board-comments.js'].setupCommentForm(document.querySelector('.board-card'))")
	assert "d-none" not in js.classes(".board-card-comment-form")


def test_auth_status_failure_leaves_comments_open(js: JsPage) -> None:
	js.route("/auth/status", status=500)
	_card(js)
	js.settle("__loaded['board-comments.js'].loadBoardAuthStatus()")
	js.route("/auth/status", error="offline")
	js.settle("__loaded['board-comments.js'].loadBoardAuthStatus()")
	js.run("__loaded['board-comments.js'].setupCommentForm(document.querySelector('.board-card'))")
	assert "d-none" not in js.classes(".board-card-comment-form")


def test_submitting_a_comment_posts_and_reloads(js: JsPage) -> None:
	js.route("comments/create", status=200, text="ok")
	js.route("comments/list", body=[{"author": "ada", "content": "hello"}])
	_card(js)
	js.run("__loaded['board-comments.js'].setupCommentForm(document.querySelector('.board-card'))")
	js.run("__loaded['board-comments.js'].setupCommentForm(document.querySelector('.board-card'))")
	js.dispatch(".board-card-comment-form", "submit")
	assert requested(js, "comments/create") is False
	js.set_prop(".board-card-comment-input", "value", "  hello  ")
	js.dispatch(".board-card-comment-form", "submit")
	assert any("content=hello" in str(item["url"]) for item in js.requests())
	assert js.prop(".board-card-comment-input", "value") == ""
	assert js.text(".board-card-comment-content") == "hello"


def test_comment_post_errors_are_shown(js: JsPage) -> None:
	_card(js)
	js.run("__loaded['board-comments.js'].setupCommentForm(document.querySelector('.board-card'))")
	js.set_prop(".board-card-comment-input", "value", "hello")
	for status, snippet in ((401, "Not authorized"), (500, "Could not post comment")):
		js.route("comments/create", status=status, text="no")
		js.dispatch(".board-card-comment-form", "submit")
		assert snippet in js.text(".board-task-error-hint")
		js.tick()
	js.route("comments/create", error="offline")
	js.set_prop(".board-card-comment-input", "value", "hello")
	js.dispatch(".board-card-comment-form", "submit")
	assert "Could not post comment" in js.text(".board-task-error-hint")


def test_comment_form_without_a_form_or_project_does_nothing(js: JsPage) -> None:
	js.set_html('<div class="board-columns" data-project="demo"><div class="board-card" data-task-ref="t"></div></div>')
	js.load("board-comments.js")
	js.run("__loaded['board-comments.js'].setupCommentForm(document.querySelector('.board-card'))")
	js.set_html(
		'<div class="board-columns"><div class="board-card" data-task-ref="t">'
		'<form class="board-card-comment-form"><textarea class="board-card-comment-input"></textarea></form>'
		'<div class="board-card-comment-signin-hint d-none"></div></div></div>'
	)
	js.set_location("http://127.0.0.1/")
	js.run("__loaded['board-comments.js'].setupCommentForm(document.querySelector('.board-card'))")
	js.set_prop(".board-card-comment-input", "value", "hello")
	js.dispatch(".board-card-comment-form", "submit")
	assert requested(js, "comments/create") is False