# retoor <retoor@molodetz.nl>


from tests.api.quizzes._helpers import (
    CHOICE,
    JSON,
    NUMERIC,
    add_question,
    build_published,
    create_quiz,
    publish,
    signup,
)
from tests.conftest import BASE_URL


def _frozen_quiz():
    session, _ = signup()
    slug = create_quiz(session, "Frozen quiz")
    add_question(session, slug, CHOICE)
    question_uid = session.get(f"{BASE_URL}/quizzes/{slug}/edit", headers=JSON).json()[
        "questions"
    ][0]["uid"]
    publish(session, slug)
    return session, slug, question_uid


def test_publishing_an_empty_quiz_is_refused(app_server, seeded_db):
    session, _ = signup()
    slug = create_quiz(session, "Empty quiz")
    response = publish(session, slug)
    assert response.status_code == 400
    assert "question" in response.json()["error"]["message"]


def test_a_refused_publish_leaves_the_quiz_a_draft(app_server, seeded_db):
    session, _ = signup()
    slug = create_quiz(session, "Still a draft")
    publish(session, slug)
    payload = session.get(f"{BASE_URL}/quizzes/{slug}", headers=JSON).json()
    assert payload["quiz"]["status"] == "draft"


def test_the_builder_lists_the_validation_problems(app_server, seeded_db):
    session, _ = signup()
    slug = create_quiz(session, "Checklist quiz")
    payload = session.get(f"{BASE_URL}/quizzes/{slug}/edit", headers=JSON).json()
    assert payload["validation_errors"]


def test_a_free_text_without_criteria_blocks_publishing(app_server, seeded_db):
    from devplacepy.database import get_table, refresh_snapshot

    session, _ = signup()
    slug = create_quiz(session, "Incomplete free text quiz")
    add_question(session, slug, NUMERIC)
    refresh_snapshot()
    quiz = get_table("quizzes").find_one(slug=slug)
    question = get_table("quiz_questions").find_one(quiz_uid=quiz["uid"], deleted_at=None)
    get_table("quiz_questions").update(
        {"uid": question["uid"], "kind": "free_text", "expected_answer": "", "grading_criteria": ""},
        ["uid"],
    )
    refresh_snapshot()
    response = publish(session, slug)
    assert response.status_code == 400


def test_a_single_choice_without_a_correct_option_blocks_publishing(app_server, seeded_db):
    from devplacepy.database import get_table, refresh_snapshot

    session, _ = signup()
    slug = create_quiz(session, "Broken choice quiz")
    add_question(session, slug, CHOICE)
    refresh_snapshot()
    quiz = get_table("quizzes").find_one(slug=slug)
    get_table("quiz_options").update_many(
        [
            {"uid": row["uid"], "is_correct": 0}
            for row in get_table("quiz_options").find(quiz_uid=quiz["uid"], deleted_at=None)
        ],
        ["uid"],
    )
    refresh_snapshot()
    assert publish(session, slug).status_code == 400


def test_publishing_a_complete_quiz_succeeds(app_server, seeded_db):
    session, _ = signup()
    slug = create_quiz(session, "Complete quiz")
    add_question(session, slug, CHOICE)
    response = publish(session, slug)
    assert response.status_code == 200
    assert response.json()["data"]["status"] == "published"


def test_publishing_twice_is_harmless(app_server, seeded_db):
    session, _ = signup()
    slug = build_published(session, title="Twice published quiz")
    assert publish(session, slug).status_code == 200


def test_only_the_owner_can_publish(app_server, seeded_db):
    owner, _ = signup()
    slug = create_quiz(owner, "Owner only quiz")
    add_question(owner, slug, CHOICE)
    other, _ = signup()
    assert publish(other, slug).status_code == 404


def test_a_published_quiz_refuses_a_settings_edit(app_server, seeded_db):
    session, slug, _ = _frozen_quiz()
    response = session.post(
        f"{BASE_URL}/quizzes/edit/{slug}", data={"title": "Renamed"}, headers=JSON
    )
    assert response.status_code == 400


def test_a_published_quiz_refuses_a_new_question(app_server, seeded_db):
    session, slug, _ = _frozen_quiz()
    assert add_question(session, slug, NUMERIC).status_code == 400


def test_a_published_quiz_refuses_a_question_edit(app_server, seeded_db):
    session, slug, question_uid = _frozen_quiz()
    response = session.post(
        f"{BASE_URL}/quizzes/{slug}/questions/{question_uid}", data=CHOICE, headers=JSON
    )
    assert response.status_code == 400


def test_a_published_quiz_refuses_a_question_delete(app_server, seeded_db):
    session, slug, question_uid = _frozen_quiz()
    response = session.post(
        f"{BASE_URL}/quizzes/{slug}/questions/{question_uid}/delete", headers=JSON
    )
    assert response.status_code == 400


def test_a_published_quiz_refuses_a_reorder(app_server, seeded_db):
    session, slug, question_uid = _frozen_quiz()
    response = session.post(
        f"{BASE_URL}/quizzes/{slug}/questions/reorder",
        data={"order": question_uid},
        headers=JSON,
    )
    assert response.status_code == 400


def test_a_refused_write_leaves_the_question_untouched(app_server, seeded_db):
    session, slug, question_uid = _frozen_quiz()
    before = session.get(f"{BASE_URL}/quizzes/{slug}/edit", headers=JSON).json()["questions"]
    session.post(
        f"{BASE_URL}/quizzes/{slug}/questions/{question_uid}",
        data={**CHOICE, "prompt": "Rewritten"},
        headers=JSON,
    )
    after = session.get(f"{BASE_URL}/quizzes/{slug}/edit", headers=JSON).json()["questions"]
    assert before == after


def test_there_is_no_unpublish_route(app_server, seeded_db):
    session, slug, _ = _frozen_quiz()
    assert session.post(f"{BASE_URL}/quizzes/{slug}/unpublish", headers=JSON).status_code == 404


def test_delete_still_works_on_a_published_quiz(app_server, seeded_db):
    session, slug, _ = _frozen_quiz()
    assert session.post(f"{BASE_URL}/quizzes/delete/{slug}", headers=JSON).status_code == 200


def test_the_builder_renders_read_only_after_publishing(app_server, seeded_db):
    session, slug, _ = _frozen_quiz()
    page = session.get(f"{BASE_URL}/quizzes/{slug}/edit").text
    assert "permanently frozen" in page
    assert "Add a question" not in page


def test_the_publish_flag_disappears_from_the_quiz(app_server, seeded_db):
    session, slug, _ = _frozen_quiz()
    payload = session.get(f"{BASE_URL}/quizzes/{slug}", headers=JSON).json()
    assert payload["quiz"]["viewer_can_edit"] is False
    assert payload["quiz"]["published_at"]
