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