# retoor <retoor@molodetz.nl>

import time

import requests
from playwright.sync_api import expect

from devplacepy.database import get_setting, get_table, refresh_snapshot, set_setting
from devplacepy.utils import clear_user_cache
from tests.conftest import BASE_URL

JSON = {"Accept": "application/json"}


def _seed_post(user):
    session = requests.Session()
    session.post(
        f"{BASE_URL}/auth/login",
        data={"email": user["email"], "password": user["password"]},
        headers=JSON,
    )
    session.post(
        f"{BASE_URL}/posts/create",
        data={
            "title": "Terms gate fixture post",
            "content": "A post that exists so the vote control is present on the feed.",
        },
        headers=JSON,
    )


def _accepted_version(username):
    refresh_snapshot()
    row = get_table("users").find_one(username=username)
    return (row or {}).get("terms_version") or ""


def _restore_accepted_version(username, version):
    refresh_snapshot()
    row = get_table("users").find_one(username=username)
    if not row:
        return
    get_table("users").update({"uid": row["uid"], "terms_version": version}, ["uid"])
    clear_user_cache(row["uid"])


def _open_gate_dialog(page):
    for _ in range(40):
        page.locator(".post-card .vote-up").first.click()
        dialog = page.locator(".dialog-overlay.visible")
        try:
            dialog.wait_for(state="visible", timeout=1500)
            return dialog
        except Exception:
            time.sleep(0.5)
    return None


def test_the_gate_dialog_accepts_the_terms_and_replays_the_action(alice, seeded_db):
    page, _ = alice
    username = seeded_db["alice"]["username"]
    _seed_post(seeded_db["alice"])
    original = get_setting("terms_version", "1") or "1"
    accepted_before = _accepted_version(username)
    bumped = f"{original}-e2eaccept"
    set_setting("terms_version", bumped)
    try:
        page.goto(f"{BASE_URL}/feed", wait_until="domcontentloaded")
        page.locator(".post-card").first.wait_for(state="visible", timeout=10000)

        dialog = _open_gate_dialog(page)
        assert dialog is not None, "the terms gate dialog never appeared"

        expect(page.locator(".dialog-title")).to_have_text("Terms of Service")
        expect(page.locator(".dialog-links a")).to_have_count(3)
        expect(page.locator(".dialog-confirm")).to_have_text("Accept and continue")
        assert _accepted_version(username) != bumped

        page.locator(".dialog-confirm").click()
        page.locator(".dialog-overlay.visible").wait_for(state="hidden", timeout=10000)

        recorded = ""
        for _ in range(40):
            recorded = _accepted_version(username)
            if recorded == bumped:
                break
            time.sleep(0.5)
        assert recorded == bumped
    finally:
        set_setting("terms_version", original)
        _restore_accepted_version(username, accepted_before)


def test_declining_the_gate_dialog_records_no_acceptance(alice, seeded_db):
    page, _ = alice
    username = seeded_db["alice"]["username"]
    _seed_post(seeded_db["alice"])
    original = get_setting("terms_version", "1") or "1"
    accepted_before = _accepted_version(username)
    bumped = f"{original}-e2edecline"
    set_setting("terms_version", bumped)
    try:
        page.goto(f"{BASE_URL}/feed", wait_until="domcontentloaded")
        page.locator(".post-card").first.wait_for(state="visible", timeout=10000)

        dialog = _open_gate_dialog(page)
        assert dialog is not None, "the terms gate dialog never appeared"

        page.locator(".dialog-cancel").click()
        page.locator(".dialog-overlay.visible").wait_for(state="hidden", timeout=10000)

        assert _accepted_version(username) != bumped
    finally:
        set_setting("terms_version", original)
        _restore_accepted_version(username, accepted_before)
