from __future__ import annotations

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


def _routes(js: JsPage) -> None:
    js.route("board/list", body=[{"name": "Tasks", "task_count": 1}, {"name": "Sprint-2", "task_count": 0}])
    js.route("tasks/list", body=[])
    js.route("board-ref-manifest", body={"commits": [], "refs": []})
    js.route("/auth/status", body={"auth_enabled": False})


def test_init_waits_for_dom_content_loaded(js: JsPage) -> None:
    _routes(js)
    js.set_html(board_shell())
    js.run("document.readyState = 'loading';")
    js.load("board.js")
    assert js.value("__preloaded") == []
    js.run("document.readyState = 'complete';")
    js.run("document.dispatchEvent(new Event('DOMContentLoaded'))")
    assert len(js.value("__preloaded")) == 6


def test_selector_lists_boards_and_navigates(js: JsPage) -> None:
    _routes(js)
    js.set_html(board_shell())
    js.load("board.js")
    labels = js.value(
        "Array.from(document.querySelectorAll('#board-board-select option')).map(function(el){return el.textContent;})"
    )
    assert labels == ["Tasks (1)", "Sprint-2 (0)"]
    assert js.prop("#board-board-select", "value") == "Tasks"
    js.dispatch("#board-board-select", "change")
    assert js.value("__assigned") is None
    js.set_prop("#board-board-select", "value", "Sprint-2")
    js.dispatch("#board-board-select", "change")
    assert js.value("__assigned") == "/project/demo/board/?b=Sprint-2"


def test_unknown_current_board_is_inserted(js: JsPage) -> None:
    _routes(js)
    js.set_html(board_shell(board="Other"))
    js.load("board.js")
    assert js.prop("#board-board-select", "value") == "Other"
    assert js.text("#board-board-select option") == "Other"


def test_empty_or_failed_board_list_leaves_the_select(js: JsPage) -> None:
    js.route("board/list", body=[])
    js.route("tasks/list", body=[])
    js.route("board-ref-manifest", body={"commits": [], "refs": []})
    js.route("/auth/status", body={"auth_enabled": False})
    js.set_html(board_shell())
    js.load("board.js")
    assert js.count("#board-board-select option") == 0


def test_failed_board_list_leaves_the_select(js: JsPage) -> None:
    js.route("board/list", error="offline")
    js.route("tasks/list", body=[])
    js.route("board-ref-manifest", body={"commits": [], "refs": []})
    js.route("/auth/status", body={"auth_enabled": False})
    js.set_html(board_shell())
    js.load("board.js")
    assert js.count("#board-board-select option") == 0


def test_sprint_name_increments_and_the_form_can_be_cancelled(js: JsPage) -> None:
    _routes(js)
    js.route("board/list", body=[{"name": "Sprint-2"}, {"name": "notes"}, {"name": "Sprint-9"}])
    js.set_html(board_shell())
    js.load("board.js")
    js.click("#board-new-sprint-btn")
    assert "d-none" not in js.classes("#board-new-form")
    assert js.prop("#board-new-name", "value") == "Sprint-10"
    js.click("#board-new-cancel")
    assert "d-none" in js.classes("#board-new-form")
    js.click("#board-new-board-btn")
    assert js.prop("#board-new-name", "value") == ""


def test_create_board_navigates_or_shows_the_error(js: JsPage) -> None:
    _routes(js)
    js.route("board/create", status=200)
    js.set_html(board_shell())
    js.load("board.js")
    js.click("#board-new-board-btn")
    js.set_prop("#board-new-name", "value", "   ")
    js.dispatch("#board-new-form", "submit")
    assert requested(js, "board/create") is False
    js.set_prop("#board-new-name", "value", "My Board")
    js.dispatch("#board-new-form", "submit")
    assert js.value("__assigned") == "/project/demo/board/?b=My-Board"
    js.route("board/create", status=400, body={"detail": "taken"})
    js.set_prop("#board-new-name", "value", "Tasks")
    js.dispatch("#board-new-form", "submit")
    assert js.text("#board-new-error") == "taken"
    assert "d-none" not in js.classes("#board-new-error")
    js.route("board/create", status=400, json_error=True)
    js.dispatch("#board-new-form", "submit")
    assert js.text("#board-new-error") == "Could not create board."
    js.route("board/create", error="offline")
    js.dispatch("#board-new-form", "submit")
    assert js.text("#board-new-error") == "Could not create board."


def test_open_task_from_the_query_string(js: JsPage) -> None:
    _routes(js)
    js.route(
        "tasks/list",
        body=[{"ref": "refs/tags/tasks/task_abcd", "title": "Ship", "status": "TODO"}],
    )
    js.set_location("http://127.0.0.1/project/demo/board/?task=refs/tags/tasks/task_abcd")
    js.set_html(board_shell())
    js.load("board.js")
    assert js.count(".board-card-popout") == 0
    js.tick()
    assert "board-card-popout" in js.classes(".board-card")


def test_open_task_skips_a_card_that_is_already_open(js: JsPage) -> None:
    _routes(js)
    js.route("tasks/list", body=[{"ref": "t1", "title": "Ship", "status": "TODO"}])
    js.set_location("http://127.0.0.1/project/demo/board/?task=t1")
    js.set_html(board_shell())
    js.load("board.js")
    js.run("document.querySelector('.board-card').classList.add('board-card-popout')")
    js.tick()
    assert js.count(".board-card-popout-overlay") == 0


def test_missing_query_task_does_not_open_a_card(js: JsPage) -> None:
    _routes(js)
    js.set_html(board_shell())
    js.load("board.js")
    js.tick()
    assert js.count(".board-card-popout-overlay") == 0


def test_init_without_a_project_skips_the_network(js: JsPage) -> None:
    js.set_html('<div class="board-columns"></div><select id="board-board-select"></select>')
    js.set_location("http://127.0.0.1/")
    js.load("board.js")
    assert requested(js, "board/list") is False
    assert requested(js, "tasks/list") is False


def test_sprint_suggestion_starts_at_one_before_the_list_loads(js: JsPage) -> None:
    js.route("tasks/list", body=[])
    js.route("board-ref-manifest", body={"commits": [], "refs": []})
    js.route("/auth/status", body={"auth_enabled": False})
    js.set_html(board_shell())
    js.load("board.js")
    js.click("#board-new-sprint-btn")
    assert js.prop("#board-new-name", "value") == "Sprint-1"