"""Putting a point where it belongs.

Points were append-only: a new one landed last and nothing could move it. So
"and here is the menu opening", which belongs second, read as the last beat,
after the closing remarks.
"""

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


def _step(client, oid, title):
    r = client.post(f"/api/options/{oid}/walkthrough",
                    json={"title": title, "body_md": "", "target_selector": ""})
    assert r.status_code == 200, r.text
    return r.json()["id"]


def _titles(client, oid):
    return [s["title"] for s in
            client.get(f"/api/options/{oid}/walkthrough").json()["steps"]]


def test_a_point_can_be_moved_to_the_front(client, kit):
    iid = make_project(client, kit)
    _sid, oid = add_screen_option(client, iid)
    a = _step(client, oid, "Start here")
    b = _step(client, oid, "Your number")
    c = _step(client, oid, "The menu opening")
    assert _titles(client, oid) == ["Start here", "Your number", "The menu opening"]

    r = client.post(f"/api/options/{oid}/walkthrough/reorder",
                    json={"step_ids": [a, c, b]})
    assert r.status_code == 200, r.text
    assert _titles(client, oid) == ["Start here", "The menu opening", "Your number"]


def test_points_left_out_of_the_order_keep_their_place_at_the_end(client, kit):
    """Naming only the two you care about must not silently drop the rest."""
    iid = make_project(client, kit)
    _sid, oid = add_screen_option(client, iid)
    a = _step(client, oid, "One")
    b = _step(client, oid, "Two")
    _c = _step(client, oid, "Three")

    client.post(f"/api/options/{oid}/walkthrough/reorder", json={"step_ids": [b, a]})
    assert _titles(client, oid) == ["Two", "One", "Three"]


def test_an_order_naming_a_deleted_point_is_refused_whole(client, kit):
    """Half a reorder would leave a client reading a scrambled walkthrough."""
    iid = make_project(client, kit)
    _sid, oid = add_screen_option(client, iid)
    a = _step(client, oid, "One")
    b = _step(client, oid, "Two")

    r = client.post(f"/api/options/{oid}/walkthrough/reorder",
                    json={"step_ids": [b, a, 9999]})
    assert r.status_code == 400
    assert r.json()["detail"]["error_code"] == "NO_SUCH_STEP"
    assert _titles(client, oid) == ["One", "Two"]


def test_reordering_is_the_manager_side(client, kit):
    iid = make_project(client, kit)
    _sid, oid = add_screen_option(client, iid)
    a = _step(client, oid, "One")
    as_user(client, "cleo")
    r = client.post(f"/api/options/{oid}/walkthrough/reorder", json={"step_ids": [a]})
    assert r.status_code == 403


def test_a_point_moves_to_a_named_position(client, kit):
    """The editor sends the whole order after moving one point to the position
    typed into the box, which is what "put this first" means. Walking a late
    idea up the list one press at a time is not editing, it is bookkeeping."""
    iid = make_project(client, kit)
    _sid, oid = add_screen_option(client, iid)
    a = _step(client, oid, "One")
    b = _step(client, oid, "Two")
    c = _step(client, oid, "Three")
    d = _step(client, oid, "Late idea")

    # "Late idea" is point 4; make it point 2.
    r = client.post(f"/api/options/{oid}/walkthrough/reorder",
                    json={"step_ids": [a, d, b, c]})
    assert r.status_code == 200, r.text
    assert _titles(client, oid) == ["One", "Late idea", "Two", "Three"]

    # And to the very front.
    client.post(f"/api/options/{oid}/walkthrough/reorder",
                json={"step_ids": [d, a, b, c]})
    assert _titles(client, oid) == ["Late idea", "One", "Two", "Three"]


def test_a_demo_click_waits_while_the_point_is_read(client, kit):
    """It fired a quarter of a second after the beat opened, so the design
    changed while the reader was still on the first line. Two seconds by
    default, and per point, because the right wait depends on the sentence."""
    iid = make_project(client, kit)
    _sid, oid = add_screen_option(client, iid)
    sid = _step(client, oid, "Services, one hover away")

    step = client.get(f"/api/options/{oid}/walkthrough").json()["steps"][0]
    assert step["click_delay_seconds"] == 2

    r = client.patch(f"/api/walkthrough/{sid}", json={
        "click_selector": ".services .mi:nth-of-type(2) > a",
        "click_delay_seconds": 5, "click_dismiss_seconds": 0})
    assert r.status_code == 200, r.text

    step = client.get(f"/api/options/{oid}/walkthrough").json()["steps"][0]
    assert step["click_delay_seconds"] == 5
    assert step["click_dismiss_seconds"] == 0      # 0 means leave it open


def test_the_wait_is_bounded(client, kit):
    iid = make_project(client, kit)
    _sid, oid = add_screen_option(client, iid)
    sid = _step(client, oid, "One")
    assert client.patch(f"/api/walkthrough/{sid}",
                        json={"click_delay_seconds": -1}).status_code == 422
    assert client.patch(f"/api/walkthrough/{sid}",
                        json={"click_delay_seconds": 601}).status_code == 422


def test_a_point_can_be_said_in_a_card(client, kit):
    """A welcome is not a point about the header. Said in a centred card
    over the dimmed design it reads as what it is; the flag rides with the
    point and is off unless asked for."""
    iid = make_project(client, kit)
    _sid, oid = add_screen_option(client, iid)
    a = _step(client, oid, "Start here")
    r = client.post(f"/api/options/{oid}/walkthrough",
                    json={"title": "Welcome", "body_md": "This is the walkthrough.",
                          "target_selector": "", "modal": True})
    assert r.status_code == 200, r.text
    steps = client.get(f"/api/options/{oid}/walkthrough").json()["steps"]
    assert [s["modal"] for s in steps] == [False, True]

    r = client.patch(f"/api/walkthrough/{a}", json={"modal": True})
    assert r.status_code == 200, r.text
    r = client.patch(f"/api/walkthrough/{steps[1]['id']}", json={"modal": False})
    assert r.status_code == 200, r.text
    steps = client.get(f"/api/options/{oid}/walkthrough").json()["steps"]
    assert [s["modal"] for s in steps] == [True, False]
