"""Draft and published screens.

A screen being worked on is ours alone; the client meets it when we publish it,
not when we start it.
"""

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


def _screens(client, iid):
    return client.get(f"/api/projects/{iid}").json()["screens"]


def test_a_new_screen_starts_as_a_draft(client, kit):
    """You cannot accidentally show someone half a page."""
    iid = make_project(client, kit)
    add_screen_option(client, iid, "Your Team", published=False)
    assert _screens(client, iid)[0]["published"] is False
    as_user(client, "cleo")
    assert _screens(client, iid) == []


def test_publishing_hands_it_to_the_client(client, kit):
    iid = make_project(client, kit)
    sid, _oid = add_screen_option(client, iid, "Your Team", published=False)
    client.patch(f"/api/screens/{sid}", json={"published": True})
    as_user(client, "cleo")
    assert [s["title"] for s in _screens(client, iid)] == ["Your Team"]


def test_a_draft_does_not_hold_the_project_open(client, kit):
    """The rollup answers "where does the CLIENT's decision stand", and a draft
    is not in front of them to decide on."""
    iid = make_project(client, kit)
    sid, oid = add_screen_option(client, iid, "Homepage")
    draft_sid, _ = add_screen_option(client, iid, "Your Team", published=False)
    client.post(f"/api/projects/{iid}/send")

    as_user(client, "cleo")
    client.post(f"/api/screens/{sid}/select", json={"option_id": oid})
    # Homepage decided; the draft screen is not a second decision owed.
    assert client.get(f"/api/projects/{iid}/status").json()["state"] == "done"
    summary = client.get(f"/api/projects/{iid}/summary").json()
    assert [d["screen"] for d in summary["decided"]] == ["Homepage"]
    assert summary["undecided"] == []


def test_publishing_it_reopens_the_decision(client, kit):
    iid = make_project(client, kit)
    sid, oid = add_screen_option(client, iid, "Homepage")
    draft_sid, _ = add_screen_option(client, iid, "Your Team", published=False)
    client.post(f"/api/projects/{iid}/send")
    as_user(client, "cleo")
    client.post(f"/api/screens/{sid}/select", json={"option_id": oid})
    assert client.get(f"/api/projects/{iid}/status").json()["state"] == "done"

    as_user(client, "mara")
    client.patch(f"/api/screens/{draft_sid}", json={"published": True})
    # Now there IS a second decision owed, and the board says so.
    assert client.get(f"/api/projects/{iid}/status").json()["state"] == "waiting_client"


def test_a_draft_is_absent_from_the_contents_rail_and_the_counts(client, kit):
    iid = make_project(client, kit)
    add_screen_option(client, iid, "Homepage")
    add_screen_option(client, iid, "Your Team", published=False)

    as_user(client, "cleo")
    titles = [s["title"] for s in
              client.get(f"/api/projects/{iid}/contents").json()["sections"]]
    assert titles == ["Tool Introduction", "Homepage"]
    rows = client.get("/api/projects").json()["projects"]
    assert next(r for r in rows if r["id"] == iid)["screen_count"] == 1


def test_existing_screens_were_not_hidden_by_the_change(client, kit):
    """The migration backfills TRUE: a migration must not make things vanish
    from a live board. Only NEW screens start as drafts."""
    from app.db import get_session_factory
    from app.models import Screen
    from sqlalchemy import select

    iid = make_project(client, kit)
    sid, _oid = add_screen_option(client, iid, "Homepage", published=False)
    # Simulate a pre-existing row as the migration leaves it.
    with get_session_factory()() as db:
        row = db.scalar(select(Screen).where(Screen.id == sid))
        row.published = True
        db.commit()
    as_user(client, "cleo")
    assert [s["title"] for s in _screens(client, iid)] == ["Homepage"]


def test_only_the_team_can_publish(client, kit):
    iid = make_project(client, kit)
    sid, _oid = add_screen_option(client, iid)
    as_user(client, "cleo")
    assert client.patch(f"/api/screens/{sid}",
                        json={"published": True}).status_code == 403
