"""A conversation about a BEAT of the walkthrough.

A point in the tour is a subject the way a screen is: one thread, asked where
the point is shown. Before this, a question about a beat meant pausing the
tour and dropping a pin near the spot — a spatial note for a question that
was about the words. Pins stay the primary act for "about this bit".
"""

from tests.conftest import as_user
from tests.test_domain import add_screen_option, make_project


def add_step(client, oid, title="The five doors", requires_approval=False):
    r = client.post(f"/api/options/{oid}/walkthrough",
                    json={"title": title, "body_md": "No hero — the practice "
                          "areas ARE the first screen.",
                          "rect": {"x": 0, "y": 8, "w": 100, "h": 40},
                          "requires_approval": requires_approval})
    assert r.status_code == 200, r.text
    return r.json()["id"]


def test_a_beat_starts_with_no_conversation(client, kit):
    iid = make_project(client, kit)
    _sid, oid = add_screen_option(client, iid)
    step = add_step(client, oid)
    as_user(client, "cleo")
    assert client.get(f"/api/steps/{step}/thread").json() == {
        "thread_id": None, "resolved": False, "comments": []}
    wt = client.get(f"/api/options/{oid}/walkthrough").json()["steps"][0]
    assert (wt["comment_count"], wt["thread_open"]) == (0, False)


def test_the_client_can_ask_about_a_point_without_leaving_the_tour(client, kit):
    iid = make_project(client, kit)
    _sid, oid = add_screen_option(client, iid)
    step = add_step(client, oid)
    as_user(client, "cleo")
    r = client.post(f"/api/steps/{step}/comments",
                    json={"body_md": "Is this the final wording?"})
    assert r.status_code == 200, r.text

    body = client.get(f"/api/steps/{step}/thread").json()
    assert body["thread_id"] is not None
    assert body["comments"][0]["author_side"] == "client"
    assert "final wording" in body["comments"][0]["body_md"]

    # The tour's own payload badges the point, and so does the outline.
    wt = client.get(f"/api/options/{oid}/walkthrough").json()["steps"][0]
    assert (wt["comment_count"], wt["thread_open"]) == (1, True)
    beats = client.get(f"/api/projects/{iid}/contents").json()["sections"][1]["items"][0]["beats"]
    assert [(b["id"], b["comment_count"], b["open"]) for b in beats] == [(step, 1, True)]


def test_a_beat_has_at_most_one_thread(client, kit):
    iid = make_project(client, kit)
    _sid, oid = add_screen_option(client, iid)
    step = add_step(client, oid)
    as_user(client, "cleo")
    first = client.post(f"/api/steps/{step}/comments", json={"body_md": "One."}).json()["id"]
    second = client.post(f"/api/steps/{step}/comments", json={"body_md": "Two."}).json()["id"]
    assert first == second
    assert len(client.get(f"/api/steps/{step}/thread").json()["comments"]) == 2


def test_a_beat_conversation_turns_the_board(client, kit):
    """Same rule as a screen's conversation: feedback that does not move the
    status is feedback left into silence."""
    iid = make_project(client, kit)
    _sid, oid = add_screen_option(client, iid)
    step = add_step(client, oid)
    client.post(f"/api/projects/{iid}/send")
    assert client.get(f"/api/projects/{iid}/status").json()["state"] == "waiting_client"

    as_user(client, "cleo")
    tid = client.post(f"/api/steps/{step}/comments",
                      json={"body_md": "Why is this number so big?"}).json()["id"]
    assert client.get(f"/api/projects/{iid}/status").json()["state"] == "waiting_agency"

    as_user(client, "mara")
    assert client.post(f"/api/threads/{tid}/resolve").status_code == 200
    assert client.get(f"/api/projects/{iid}/status").json()["state"] == "waiting_client"
    wt = client.get(f"/api/options/{oid}/walkthrough").json()["steps"][0]
    assert (wt["comment_count"], wt["thread_open"]) == (1, False)


def test_the_notification_links_back_into_the_tour_at_that_point(client, kit):
    """The team member who is told about the question should land on the
    point itself, tour open, not on the board."""
    iid = make_project(client, kit)
    _sid, oid = add_screen_option(client, iid)
    add_step(client, oid, title="First")
    second = add_step(client, oid, title="Second")
    client.post(f"/api/projects/{iid}/send")
    as_user(client, "cleo")
    client.post(f"/api/steps/{second}/comments", json={"body_md": "@mara this one?"})

    as_user(client, "mara")
    urls = [n["url"] for n in client.get("/api/notifications").json()["notifications"]]
    assert f"/p/{iid}/o/{oid}?mode=play&step=2" in urls


def test_pins_are_untouched_by_any_of_this(client, kit):
    iid = make_project(client, kit)
    _sid, oid = add_screen_option(client, iid)
    step = add_step(client, oid)
    client.post(f"/api/projects/{iid}/send")
    as_user(client, "cleo")
    client.post(f"/api/steps/{step}/comments", json={"body_md": "About the point."})
    assert client.get(f"/api/options/{oid}/pins").json()["pins"] == []
    assert client.get(f"/api/projects/{iid}/status").json()["counts"]["client_open"] == 1


def test_an_outsider_cannot_read_or_start_one(client, kit):
    iid = make_project(client, kit)
    _sid, oid = add_screen_option(client, iid)
    step = add_step(client, oid)
    as_user(client, "nate")
    assert client.get(f"/api/steps/{step}/thread").status_code == 404
    assert client.post(f"/api/steps/{step}/comments",
                       json={"body_md": "hi"}).status_code == 404
