# retoor <retoor@molodetz.nl>

import time
import requests
from tests.conftest import BASE_URL
from devplacepy.database import get_table
_counter_polls = [0]
AJAX_polls = {"X-Requested-With": "fetch"}
def _session_polls():
    _counter_polls[0] += 1
    name = f"pol{int(time.time() * 1000)}{_counter_polls[0]}"
    s = requests.Session()
    s.post(
        f"{BASE_URL}/auth/signup",
        data={
            "username": name,
            "email": f"{name}@t.dev",
            "password": "secret123",
            "confirm_password": "secret123",
            "birth_date": "1990-01-01",
            "accept_terms": "1",
        },
        allow_redirects=True,
    )
    return s, name
def _create_post_polls(session, title, question, options):
    fields = [
        ("content", "Poll host post content for tests."),
        ("title", title),
        ("topic", "question"),
        ("poll_question", question),
    ]
    fields.extend(("poll_options", option) for option in options)
    r = session.post(f"{BASE_URL}/posts/create", data=fields, allow_redirects=False)
    slug = r.headers["location"].split("/posts/")[-1]
    return get_table("posts").find_one(slug=slug)["uid"]
def _poll_for(post_uid):
    poll = get_table("polls").find_one(post_uid=post_uid)
    options = list(
        get_table("poll_options").find(poll_uid=poll["uid"], order_by=["position"])
    )
    return poll, options
def _create_plain_post_polls(session, title):
    r = session.post(
        f"{BASE_URL}/posts/create",
        data={
            "content": "Plain post awaiting a poll on edit.",
            "title": title,
            "topic": "question",
        },
        allow_redirects=False,
    )
    slug = r.headers["location"].split("/posts/")[-1]
    return slug, get_table("posts").find_one(slug=slug)["uid"]


def test_valid_poll_persists(app_server):
    s, _ = _session_polls()
    title = f"valid-poll-{int(time.time() * 1000)}"
    post_uid = _create_post_polls(s, title, "Tabs or spaces?", ["Tabs", "Spaces", "Both"])
    poll, options = _poll_for(post_uid)
    assert poll is not None
    assert len(options) == 3


def test_poll_dropped_with_one_option(app_server):
    s, _ = _session_polls()
    title = f"one-option-{int(time.time() * 1000)}"
    post_uid = _create_post_polls(s, title, "Only one?", ["Solo"])
    assert get_table("polls").find_one(post_uid=post_uid) is None


def test_poll_dropped_without_question(app_server):
    s, _ = _session_polls()
    title = f"no-question-{int(time.time() * 1000)}"
    post_uid = _create_post_polls(s, title, "", ["Tabs", "Spaces"])
    assert get_table("polls").find_one(post_uid=post_uid) is None


def test_vote_records_choice(app_server):
    s, _ = _session_polls()
    title = f"vote-{int(time.time() * 1000)}"
    post_uid = _create_post_polls(s, title, "Pick one", ["A", "B"])
    poll, options = _poll_for(post_uid)
    r = s.post(
        f"{BASE_URL}/polls/{poll['uid']}/vote",
        data={"option_uid": options[0]["uid"]},
        headers=AJAX_polls,
    )
    payload = r.json()
    assert payload["total"] == 1
    assert payload["my_choice"] == options[0]["uid"]
    assert get_table("poll_votes").count(poll_uid=poll["uid"]) == 1


def test_switch_vote_moves_choice(app_server):
    s, _ = _session_polls()
    title = f"switch-{int(time.time() * 1000)}"
    post_uid = _create_post_polls(s, title, "Pick one", ["A", "B"])
    poll, options = _poll_for(post_uid)
    s.post(
        f"{BASE_URL}/polls/{poll['uid']}/vote",
        data={"option_uid": options[0]["uid"]},
        headers=AJAX_polls,
    )
    r = s.post(
        f"{BASE_URL}/polls/{poll['uid']}/vote",
        data={"option_uid": options[1]["uid"]},
        headers=AJAX_polls,
    )
    payload = r.json()
    assert payload["my_choice"] == options[1]["uid"]
    assert payload["total"] == 1


def test_repeat_same_option_retracts(app_server):
    s, _ = _session_polls()
    title = f"retract-{int(time.time() * 1000)}"
    post_uid = _create_post_polls(s, title, "Pick one", ["A", "B"])
    poll, options = _poll_for(post_uid)
    s.post(
        f"{BASE_URL}/polls/{poll['uid']}/vote",
        data={"option_uid": options[0]["uid"]},
        headers=AJAX_polls,
    )
    r = s.post(
        f"{BASE_URL}/polls/{poll['uid']}/vote",
        data={"option_uid": options[0]["uid"]},
        headers=AJAX_polls,
    )
    payload = r.json()
    assert payload["my_choice"] is None
    assert payload["total"] == 0
    assert get_table("poll_votes").count(poll_uid=poll["uid"], deleted_at=None) == 0


def test_vote_invalid_option_returns_400(app_server):
    s, _ = _session_polls()
    title = f"badopt-{int(time.time() * 1000)}"
    post_uid = _create_post_polls(s, title, "Pick one", ["A", "B"])
    poll, _ = _poll_for(post_uid)
    r = s.post(
        f"{BASE_URL}/polls/{poll['uid']}/vote",
        data={"option_uid": "not-a-real-option"},
        headers=AJAX_polls,
    )
    assert r.status_code == 400


def test_vote_requires_login(app_server):
    s, _ = _session_polls()
    title = f"authvote-{int(time.time() * 1000)}"
    post_uid = _create_post_polls(s, title, "Pick one", ["A", "B"])
    poll, options = _poll_for(post_uid)
    anon = requests.Session()
    r = anon.post(
        f"{BASE_URL}/polls/{poll['uid']}/vote",
        data={"option_uid": options[0]["uid"]},
        headers=AJAX_polls,
        allow_redirects=False,
    )
    assert r.status_code == 303
    assert get_table("poll_votes").count(poll_uid=poll["uid"]) == 0


def test_multi_field_options_keep_embedded_commas(app_server):
    s, _ = _session_polls()
    title = f"comma-label-{int(time.time() * 1000)}"
    post_uid = _create_post_polls(s, title, "Sure?", ["Yes, definitely", "No, never"])
    _, options = _poll_for(post_uid)
    assert [option["label"] for option in options] == ["Yes, definitely", "No, never"]
