# retoor <retoor@molodetz.nl>

import time
import pytest
import requests
from tests.conftest import BASE_URL
from devplacepy.database import get_table, refresh_snapshot, set_setting

_counter_dc = [0]


@pytest.fixture(scope="module", autouse=True)
def _devrant_settings(app_server):
    for key, value in {
        "rate_limit_per_minute": "1000000",
        "rate_limit_window_seconds": "60",
        "registration_open": "1",
        "maintenance_mode": "0",
        "devrant_api_enabled": "1",
        "session_max_age_days": "7",
    }.items():
        set_setting(key, value)
    yield


def _name(prefix="drc"):
    _counter_dc[0] += 1
    return f"{prefix}{int(time.time() * 1000)}{_counter_dc[0]}"


def _register(password="secret123"):
    name = _name()
    for _ in range(20):
        body = requests.post(
            f"{BASE_URL}/api/users",
            data={"username": name, "email": f"{name}@t.dev", "password": password},
        ).json()
        if body.get("success"):
            at = body["auth_token"]
            return name, {
                "token_id": at["id"],
                "token_key": at["key"],
                "user_id": at["user_id"],
            }
        time.sleep(0.3)
    raise AssertionError("registration did not open")


def _rant(params):
    return requests.post(
        f"{BASE_URL}/api/devrant/rants",
        data={**params, "rant": "host rant for comment tests"},
    ).json()["rant_id"]


def _comment(rant_id, author, text="a comment body for devrant"):
    requests.post(
        f"{BASE_URL}/api/devrant/rants/{rant_id}/comments",
        data={**author, "comment": text},
    )
    refresh_snapshot()
    post_uid = get_table("posts").find_one(id=rant_id)["uid"]
    row = max(
        get_table("comments").find(target_uid=post_uid, deleted_at=None),
        key=lambda c: c["id"],
    )
    return int(row["id"]), row["uid"]


def test_get_comment(app_server):
    _, owner = _register()
    rant_id = _rant(owner)
    cid, _ = _comment(rant_id, owner)
    r = requests.get(f"{BASE_URL}/api/comments/{cid}")
    assert r.json()["success"] is True
    assert r.json()["comment"]


def test_get_comment_unknown(app_server):
    r = requests.get(f"{BASE_URL}/api/comments/999999999")
    assert r.json()["success"] is False


def test_edit_comment_owner(app_server):
    _, owner = _register()
    rant_id = _rant(owner)
    cid, cuid = _comment(rant_id, owner)
    r = requests.post(
        f"{BASE_URL}/api/comments/{cid}", data={**owner, "comment": "edited comment body"}
    )
    assert r.json()["success"] is True
    refresh_snapshot()
    assert get_table("comments").find_one(uid=cuid)["content"] == "edited comment body"


def test_edit_comment_non_owner_rejected(app_server):
    _, owner = _register()
    _, other = _register()
    rant_id = _rant(owner)
    cid, _ = _comment(rant_id, owner)
    r = requests.post(
        f"{BASE_URL}/api/comments/{cid}", data={**other, "comment": "hijack content"}
    )
    assert r.json()["success"] is False
    assert r.json().get("fail_reason") == "not_owner"


def test_edit_comment_requires_auth(app_server):
    _, owner = _register()
    rant_id = _rant(owner)
    cid, _ = _comment(rant_id, owner)
    r = requests.post(f"{BASE_URL}/api/comments/{cid}", data={"comment": "x"})
    assert r.status_code == 401


def test_delete_comment_owner(app_server):
    _, owner = _register()
    rant_id = _rant(owner)
    cid, cuid = _comment(rant_id, owner)
    r = requests.delete(f"{BASE_URL}/api/comments/{cid}", data=owner)
    assert r.json()["success"] is True
    refresh_snapshot()
    assert get_table("comments").find_one(uid=cuid)["deleted_at"] is not None


def test_delete_comment_non_owner_rejected(app_server):
    _, owner = _register()
    _, other = _register()
    rant_id = _rant(owner)
    cid, cuid = _comment(rant_id, owner)
    r = requests.delete(f"{BASE_URL}/api/comments/{cid}", data=other)
    assert r.json()["success"] is False
    refresh_snapshot()
    assert get_table("comments").find_one(uid=cuid)["deleted_at"] is None


def test_vote_comment(app_server):
    _, owner = _register()
    _, voter = _register()
    rant_id = _rant(owner)
    cid, cuid = _comment(rant_id, owner)
    r = requests.post(
        f"{BASE_URL}/api/comments/{cid}/vote", data={**voter, "vote": 1}
    )
    assert r.json()["success"] is True
    refresh_snapshot()
    assert get_table("votes").count(target_uid=cuid, value=1) >= 1
