# retoor <retoor@molodetz.nl>

import re
from playwright.sync_api import expect
from tests.conftest import BASE_URL
def _open_composer(page):
    page.goto(f"{BASE_URL}/feed", wait_until="domcontentloaded")
    page.locator(".feed-fab").first.wait_for(state="visible", timeout=10000)
    page.locator(".feed-fab").first.click()
def _create_plain_post_engagement_ui(page, content):
    _open_composer(page)
    page.fill("#post-content", content)
    page.locator("#create-post-modal button.btn-primary:has-text('Post')").click()
    page.wait_for_url(f"{BASE_URL}/posts/*", wait_until="domcontentloaded")
from uuid import uuid4
from datetime import datetime, timedelta, timezone
from tests.conftest import BASE_URL, assert_share_copies
from devplacepy.database import get_table
from devplacepy.utils import make_combined_slug
def _seed_posts(count):
    suite = uuid4().hex[:8]
    topic = f"pag{suite}"
    users = get_table("users")
    posts = get_table("posts")
    base = datetime(2026, 1, 1, tzinfo=timezone.utc)
    for i in range(count):
        owner = str(uuid4())
        users.insert(
            {
                "uid": owner,
                "username": f"pag_{suite}_{i}",
                "terms_version": "1",
                "email": f"{suite}_{i}@test.devplace",
                "password_hash": "x",
                "role": "Member",
                "is_active": True,
                "created_at": datetime.now(timezone.utc).isoformat(),
            }
        )
        uid = str(uuid4())
        content = f"Paginated post {i}"
        posts.insert(
            {
                "uid": uid,
                "user_uid": owner,
                "slug": make_combined_slug(content, uid),
                "title": None,
                "content": content,
                "topic": topic,
                "project_uid": None,
                "image": None,
                "stars": 0,
                "created_at": (base - timedelta(seconds=i)).isoformat(),
                "deleted_at": None,
                "deleted_by": None,
            }
        )
    return topic
def _seed_post_with_comments(comment_texts, topic="devlog"):
    owner = str(uuid4())
    get_table("users").insert(
        {
            "uid": owner,
            "username": f"seed_{owner[:8]}",
            "terms_version": "1",
            "email": f"{owner[:8]}@seed.devplace",
            "password_hash": "x",
            "role": "Member",
            "is_active": True,
            "created_at": datetime.now(timezone.utc).isoformat(),
        }
    )
    post_uid = str(uuid4())
    marker = f"seedpost-{post_uid[:8]}"
    get_table("posts").insert(
        {
            "deleted_at": None,
            "deleted_by": None,
            "uid": post_uid,
            "user_uid": owner,
            "slug": make_combined_slug(marker, post_uid),
            "title": None,
            "content": marker,
            "topic": topic,
            "project_uid": None,
            "image": None,
            "stars": 0,
            "created_at": datetime.now(timezone.utc).isoformat(),
        }
    )
    comments = get_table("comments")
    base = datetime.now(timezone.utc)
    for i, text in enumerate(comment_texts):
        comments.insert(
            {
                "deleted_at": None,
                "deleted_by": None,
                "uid": str(uuid4()),
                "target_type": "post",
                "target_uid": post_uid,
                "post_uid": post_uid,
                "user_uid": owner,
                "content": text,
                "parent_uid": None,
                "created_at": (base + timedelta(seconds=i)).isoformat(),
            }
        )
    return marker, post_uid
def _create_post_ui(page, content, topic="devlog"):
    page.goto(f"{BASE_URL}/feed", wait_until="domcontentloaded")
    page.locator(".feed-fab").first.wait_for(state="visible", timeout=10000)
    page.locator(".feed-fab").first.click()
    page.check(f"input[value='{topic}']")
    page.fill("#post-content", content)
    page.locator("#create-post-modal button.btn-primary:has-text('Post')").click()
    page.wait_for_url(f"{BASE_URL}/posts/*", wait_until="domcontentloaded")
def _seed_searchable_posts():
    token = uuid4().hex[:10]
    users = get_table("users")
    posts = get_table("posts")
    base = datetime(2026, 1, 1, tzinfo=timezone.utc)
    match_title = f"Findable post {token}"
    other_title = f"Unrelated post {uuid4().hex[:10]}"
    for offset, title in ((0, match_title), (1, other_title)):
        owner = str(uuid4())
        users.insert(
            {
                "uid": owner,
                "username": f"srch_{owner[:8]}",
                "terms_version": "1",
                "email": f"{owner[:8]}@test.devplace",
                "password_hash": "x",
                "role": "Member",
                "is_active": True,
                "created_at": datetime.now(timezone.utc).isoformat(),
            }
        )
        uid = str(uuid4())
        posts.insert(
            {
                "uid": uid,
                "user_uid": owner,
                "slug": make_combined_slug(title, uid),
                "title": title,
                "content": f"Body for {title}",
                "topic": "devlog",
                "project_uid": None,
                "image": None,
                "stars": 0,
                "created_at": (base - timedelta(seconds=offset)).isoformat(),
                "deleted_at": None,
                "deleted_by": None,
            }
        )
    return token, match_title, other_title
def create_post(page, topic="random", content="Test post content", title=None):
    page.goto(f"{BASE_URL}/feed", wait_until="domcontentloaded")
    page.locator(".feed-fab").first.wait_for(state="visible", timeout=10000)
    page.locator(".feed-fab").first.click()
    page.check(f"input[value='{topic}']")
    page.fill("#post-content", content)
    if title:
        page.fill("#post-title", title)
    page.locator("#create-post-modal button.btn-primary:has-text('Post')").click()
    page.wait_for_url(f"{BASE_URL}/posts/*", wait_until="domcontentloaded")
def _profile_stars(page, username):
    page.goto(f"{BASE_URL}/profile/{username}", wait_until="domcontentloaded")
    value = page.locator(
        ".profile-stat:has(.profile-stat-label:has-text('Stars')) .profile-stat-value"
    ).first
    return int(value.text_content().strip())
import requests
def _seed_news_seo():
    from datetime import datetime, timezone
    from devplacepy.database import get_table
    from devplacepy.utils import generate_uid, make_combined_slug

    uid = generate_uid()
    title = f"SEO Test News Article {uid.split('-')[-1]}"
    slug = make_combined_slug(title, uid)
    get_table("news").insert(
        {
            "deleted_at": None,
            "deleted_by": None,
            "uid": uid,
            "slug": slug,
            "title": title,
            "description": "A seeded news article for SEO tests.",
            "content": "Body content for the seeded article.",
            "url": "https://example.com/article",
            "source_name": "ExampleSource",
            "status": "published",
            "synced_at": datetime.now(timezone.utc).isoformat(),
            "show_on_landing": 0,
            "grade": 8,
        }
    )
    return slug, uid
def _seed_owner():
    from datetime import datetime, timezone
    from uuid import uuid4
    from devplacepy.database import get_table

    uid = str(uuid4())
    get_table("users").insert(
        {
            "uid": uid,
            "username": f"seo_{uid[:8]}",
            "terms_version": "1",
            "email": f"{uid[:8]}@seo.test",
            "password_hash": "x",
            "role": "Member",
            "is_active": True,
            "created_at": datetime.now(timezone.utc).isoformat(),
        }
    )
    return uid
def _seed_post_seo(image=None):
    from datetime import datetime, timezone
    from uuid import uuid4
    from devplacepy.database import get_table
    from devplacepy.utils import make_combined_slug

    owner = _seed_owner()
    uid = str(uuid4())
    slug = make_combined_slug("SEO Detail Post", uid)
    get_table("posts").insert(
        {
            "deleted_at": None,
            "deleted_by": None,
            "uid": uid,
            "user_uid": owner,
            "slug": slug,
            "title": "SEO Detail Post",
            "content": "Body text for the SEO detail post.",
            "topic": "general",
            "project_uid": None,
            "image": image,
            "stars": 0,
            "created_at": datetime.now(timezone.utc).isoformat(),
        }
    )
    return slug, uid
def _seed_gist():
    from datetime import datetime, timezone
    from uuid import uuid4
    from devplacepy.database import get_table
    from devplacepy.utils import make_combined_slug

    owner = _seed_owner()
    uid = str(uuid4())
    slug = make_combined_slug("SEO Detail Gist", uid)
    get_table("gists").insert(
        {
            "deleted_at": None,
            "deleted_by": None,
            "uid": uid,
            "user_uid": owner,
            "slug": slug,
            "title": "SEO Detail Gist",
            "description": "Gist description for SEO tests.",
            "source_code": "print('seo')",
            "language": "python",
            "stars": 0,
            "created_at": datetime.now(timezone.utc).isoformat(),
        }
    )
    return slug, uid
def _seed_project():
    from datetime import datetime, timezone
    from uuid import uuid4
    from devplacepy.database import get_table
    from devplacepy.utils import make_combined_slug

    owner = _seed_owner()
    uid = str(uuid4())
    slug = make_combined_slug("SEO Detail Project", uid)
    get_table("projects").insert(
        {
            "deleted_at": None,
            "deleted_by": None,
            "uid": uid,
            "user_uid": owner,
            "slug": slug,
            "title": "SEO Detail Project",
            "description": "Project description for SEO tests.",
            "project_type": "software",
            "platforms": "Linux",
            "status": "Released",
            "stars": 0,
            "created_at": datetime.now(timezone.utc).isoformat(),
        }
    )
    return slug, uid
def _seed_news_image(news_uid):
    from devplacepy.database import get_table

    get_table("news_images").insert(
        {
            "deleted_at": None,
            "deleted_by": None,
            "news_uid": news_uid,
            "url": "https://example.com/seo-news-image.jpg",
        }
    )
def _seed_feed_posts(count):
    from datetime import datetime, timezone, timedelta
    from uuid import uuid4
    from devplacepy.database import get_table
    from devplacepy.utils import make_combined_slug

    owner = _seed_owner()
    topic = f"seopag{owner[:8]}"
    base = datetime(2026, 1, 1, tzinfo=timezone.utc)
    posts = get_table("posts")
    for i in range(count):
        uid = str(uuid4())
        posts.insert(
            {
                "deleted_at": None,
                "deleted_by": None,
                "uid": uid,
                "user_uid": owner,
                "slug": make_combined_slug(f"seo pag {i}", uid),
                "title": None,
                "content": f"seo pag post {i}",
                "topic": topic,
                "project_uid": None,
                "image": None,
                "stars": 0,
                "created_at": (base - timedelta(seconds=i)).isoformat(),
            }
        )
    return topic


def test_create_poll_and_vote(alice):
    page, _ = alice
    _open_composer(page)
    page.fill("#post-content", "Post that carries a poll for the UI test.")
    page.locator("[data-poll-toggle]").click()
    page.fill("#create-post-modal input[name='poll_question']", "Tabs or spaces?")
    options = page.locator("#create-post-modal input[name='poll_options']")
    options.nth(0).fill("Tabs")
    options.nth(1).fill("Spaces")
    page.locator("#create-post-modal button.btn-primary:has-text('Post')").click()
    page.wait_for_url(f"{BASE_URL}/posts/*", wait_until="domcontentloaded")

    expect(page.locator(".poll-question")).to_have_text("Tabs or spaces?")
    expect(page.locator(".poll-option")).to_have_count(2)

    page.locator(".poll-option").first.click()
    expect(page.locator(".poll-option").first).to_have_class(re.compile(r"\bchosen\b"))
    expect(
        page.locator(".poll-option").first.locator(".poll-option-pct")
    ).to_be_visible()


def test_remove_poll_does_not_create_poll(alice):
    page, _ = alice
    _open_composer(page)
    page.fill(
        "#post-content", "Post where the poll is added then removed before posting."
    )
    page.locator("[data-poll-toggle]").click()
    page.fill("#create-post-modal input[name='poll_question']", "Discarded question?")
    options = page.locator("#create-post-modal input[name='poll_options']")
    options.nth(0).fill("One")
    options.nth(1).fill("Two")
    page.locator("[data-poll-toggle]").click()
    page.locator("#create-post-modal button.btn-primary:has-text('Post')").click()
    page.wait_for_url(f"{BASE_URL}/posts/*", wait_until="domcontentloaded")
    expect(page.locator(".poll")).to_have_count(0)


def test_add_poll_to_existing_post_via_edit(alice):
    page, _ = alice
    _create_plain_post_engagement_ui(page, "Post that gains a poll through the edit modal.")
    expect(page.locator(".poll")).to_have_count(0)

    page.locator("[data-modal='edit-post-modal']").click()
    modal = page.locator("#edit-post-modal")
    expect(modal).to_be_visible()
    modal.locator("[data-poll-toggle]").click()
    modal.locator("input[name='poll_question']").fill("Do you like hedgehogs?")
    options = modal.locator("input[name='poll_options']")
    options.nth(0).fill("Yes")
    options.nth(1).fill("They are spiky")
    modal.locator("button.btn-primary:has-text('Save Changes')").click()
    page.wait_for_url(f"{BASE_URL}/posts/*", wait_until="domcontentloaded")

    expect(page.locator(".poll-question")).to_have_text("Do you like hedgehogs?")
    expect(page.locator(".poll-option")).to_have_count(2)


def test_feed_vote_voted_state_persists(alice):
    page, _ = alice
    page.goto(f"{BASE_URL}/feed", wait_until="domcontentloaded")
    page.locator(".feed-fab").first.click()
    page.fill("#post-content", "Feed vote persistence test content")
    page.locator("#create-post-modal button.btn-primary:has-text('Post')").click()
    page.wait_for_url(f"{BASE_URL}/posts/*", wait_until="domcontentloaded")
    page.goto(f"{BASE_URL}/feed", wait_until="domcontentloaded")
    card = page.locator(
        ".post-card", has_text="Feed vote persistence test content"
    ).first
    card.locator(".post-action-btn.vote-up").click()
    expect(card.locator(".post-vote-count")).to_have_text("1")
    page.goto(f"{BASE_URL}/feed", wait_until="domcontentloaded")
    card = page.locator(
        ".post-card", has_text="Feed vote persistence test content"
    ).first
    expect(card.locator(".post-action-btn.vote-up")).to_have_class(
        re.compile(r"\bvoted\b")
    )


def test_feed_card_share_button(alice):
    page, _ = alice
    page.goto(f"{BASE_URL}/feed", wait_until="domcontentloaded")
    page.locator(".feed-fab").first.click()
    page.fill("#post-content", "Feed share button test content")
    page.locator("#create-post-modal button.btn-primary:has-text('Post')").click()
    page.wait_for_url(f"{BASE_URL}/posts/*", wait_until="domcontentloaded")
    page.goto(f"{BASE_URL}/feed", wait_until="domcontentloaded")
    assert_share_copies(page, "/posts/")
    assert "/feed" in page.url


def test_create_post_devlog(alice):
    page, _ = alice
    page.goto(f"{BASE_URL}/feed", wait_until="domcontentloaded")
    page.locator(".feed-fab").click()
    page.check("input[value='devlog']")
    page.fill("#post-content", "This is a test devlog post created by Playwright")
    page.fill("#post-title", "Test Devlog Title")
    page.locator("#create-post-modal button.btn-primary:has-text('Post')").click()
    page.wait_for_url(f"{BASE_URL}/posts/*", wait_until="domcontentloaded")
    assert page.is_visible("text=Test Devlog Title")
    assert page.is_visible("text=This is a test devlog post created by Playwright")


def test_create_post_showcase(alice):
    page, _ = alice
    page.goto(f"{BASE_URL}/feed", wait_until="domcontentloaded")
    page.locator(".feed-fab").click()
    page.check("input[value='showcase']")
    page.fill("#post-content", "Check out my new project showcase")
    page.locator("#create-post-modal button.btn-primary:has-text('Post')").click()
    page.wait_for_url(f"{BASE_URL}/posts/*", wait_until="domcontentloaded")


def test_create_post_without_title(alice):
    page, _ = alice
    page.goto(f"{BASE_URL}/feed", wait_until="domcontentloaded")
    page.locator(".feed-fab").click()
    page.check("input[value='rant']")
    page.fill("#post-content", "Rant without a title")
    page.locator("#create-post-modal button.btn-primary:has-text('Post')").click()
    page.wait_for_url(f"{BASE_URL}/posts/*", wait_until="domcontentloaded")
    assert page.is_visible("text=Rant without a title")


def test_feed_inline_comment(alice):
    page, _ = alice
    marker = f"inline-{uuid4().hex[:8]}"
    _create_post_ui(page, f"{marker} post with inline comment test")
    page.goto(f"{BASE_URL}/feed", wait_until="domcontentloaded")
    card = page.locator(".post-card").filter(has_text=marker).first
    inline_form = card.locator(".comment-form")
    expect(inline_form).to_be_visible()
    inline_form.locator("textarea[name='content']").fill("Inline comment from feed")
    inline_form.locator("button.comment-form-submit").click()
    page.wait_for_url(f"{BASE_URL}/posts/*", wait_until="domcontentloaded")
    expect(
        page.locator(".comment-text:has-text('Inline comment from feed')")
    ).to_be_visible()


def test_post_edit_button(alice):
    page, _ = alice
    page.goto(f"{BASE_URL}/feed", wait_until="domcontentloaded")
    page.locator(".feed-fab").click()
    page.fill("#post-content", "Post to be edited later")
    page.fill("#post-title", "Editable Post")
    page.locator("#create-post-modal button.btn-primary:has-text('Post')").click()
    page.wait_for_url(f"{BASE_URL}/posts/*", wait_until="domcontentloaded")
    edit_btn = page.locator("button:has-text('Edit')")
    assert edit_btn.is_visible()


def test_post_edit_modal(alice):
    page, _ = alice
    page.goto(f"{BASE_URL}/feed", wait_until="domcontentloaded")
    page.locator(".feed-fab").click()
    page.fill("#post-content", "Post for edit modal test")
    page.fill("#post-title", "Edit Modal Test")
    page.locator("#create-post-modal button.btn-primary:has-text('Post')").click()
    page.wait_for_url(f"{BASE_URL}/posts/*", wait_until="domcontentloaded")
    page.click("button:has-text('Edit')")
    assert page.is_visible("h3:has-text('Edit Post')")


def test_post_edit_submit(alice):
    page, _ = alice
    page.goto(f"{BASE_URL}/feed", wait_until="domcontentloaded")
    page.locator(".feed-fab").click()
    page.fill("#post-content", "Original content for editing test")
    page.fill("#post-title", "Original Title")
    page.locator("#create-post-modal button.btn-primary:has-text('Post')").click()
    page.wait_for_url(f"{BASE_URL}/posts/*", wait_until="domcontentloaded")
    page.click("button:has-text('Edit')")
    page.fill("#edit-title", "Edited Title")
    page.fill("#edit-content", "Edited content for the post")
    page.click("button:has-text('Save Changes')")
    expect(page.locator(".post-detail-title:has-text('Edited Title')")).to_be_visible()


def test_post_page_has_structured_data(page, app_server):
    page.goto(f"{BASE_URL}/auth/signup", wait_until="domcontentloaded")
    page.fill("#username", "seo_schema_test")
    page.fill("#email", "seo_schema@test.dev")
    page.fill("#password", "secret123")
    page.fill("#confirm_password", "secret123")
    page.fill("#birth_date", "1990-01-01")
    page.check("#accept_terms")
    page.click("button:has-text('Create account')")
    page.wait_for_url("**/feed", timeout=10000, wait_until="domcontentloaded")
    page.locator(".feed-fab").click()
    page.fill(
        "#post-content",
        "This is a post for SEO testing with structured data schema validation",
    )
    page.fill("#post-title", "SEO Post For Schema")
    page.locator("#create-post-modal button.btn-primary:has-text('Post')").click()
    page.wait_for_url(
        f"{BASE_URL}/posts/*", timeout=10000, wait_until="domcontentloaded"
    )
    scripts = page.locator('script[type="application/ld+json"]')
    count = scripts.count()
    assert count >= 1
    text = scripts.first.text_content()
    assert "DiscussionForumPosting" in text or "WebSite" in text
