# retoor <retoor@molodetz.nl>

from uuid import uuid4
from datetime import datetime, timezone, timedelta
from playwright.sync_api import expect
from tests.conftest import BASE_URL
from devplacepy.database import get_table
from devplacepy.utils import make_combined_slug


def _seed_project():
    """Create a project seeded directly into DB and return (slug, uid, user_uid)."""
    owner = str(uuid4())
    get_table("users").insert(
        {
            "uid": owner,
            "username": f"dlowner_{owner[:8]}",
            "terms_version": "1",
            "email": f"{owner[:8]}@dl.test",
            "password_hash": "x",
            "role": "Member",
            "is_active": True,
            "created_at": datetime.now(timezone.utc).isoformat(),
        }
    )
    uid = str(uuid4())
    slug = make_combined_slug("E2E Devlog Project", uid)
    get_table("projects").insert(
        {
            "deleted_at": None,
            "deleted_by": None,
            "uid": uid,
            "user_uid": owner,
            "slug": slug,
            "title": "E2E Devlog Project",
            "description": "Project for devlog browser tests.",
            "project_type": "software",
            "platforms": "",
            "status": "In Development",
            "stars": 0,
            "created_at": datetime.now(timezone.utc).isoformat(),
        }
    )
    return slug, uid, owner


def _seed_project_post(project_uid, user_uid, order, title=None):
    """Insert a post linked to a project with precise ordering."""
    uid = str(uuid4())
    marker = title or f"dlpost-{uid[:8]}"
    get_table("posts").insert(
        {
            "deleted_at": None,
            "deleted_by": None,
            "uid": uid,
            "user_uid": user_uid,
            "slug": make_combined_slug(marker, uid),
            "title": marker,
            "content": f"Devlog post content {order}",
            "topic": "devlog",
            "project_uid": project_uid,
            "image": None,
            "stars": 0,
            "created_at": (datetime(2026, 1, 1, tzinfo=timezone.utc) + timedelta(seconds=order)).isoformat(),
        }
    )
    return marker, uid


def _create_project_ui(page, title):
    """Create a project via the UI."""
    page.goto(f"{BASE_URL}/projects", wait_until="domcontentloaded")
    page.locator("#create-project-btn").click()
    page.fill("#title", title)
    page.fill("#description", "Project for devlog UI test")
    page.click("button:has-text('Create Project')")
    page.wait_for_url(f"{BASE_URL}/projects/*", wait_until="domcontentloaded")
    return page.url


def test_devlog_empty_state_on_project_page(alice):
    """Project with no linked posts displays 'No devlog posts yet'."""
    page, _ = alice
    _create_project_ui(page, "Empty Devlog Project")

    devlog_section = page.locator(".project-devlog")
    expect(devlog_section).to_be_visible()
    expect(devlog_section.locator("h2:has-text('Devlog')")).to_be_visible()
    expect(page.locator(".empty-state:has-text('No devlog posts yet.')")).to_be_visible()


def test_devlog_shows_linked_post_title(alice):
    """Linked post title renders in the devlog section."""
    page, _ = alice
    slug, project_uid, owner_uid = _seed_project()

    marker = f"visible-dl-{uuid4().hex[:8]}"
    _seed_project_post(project_uid, owner_uid, 0, title=marker)

    page.goto(f"{BASE_URL}/projects/{slug}", wait_until="domcontentloaded")

    devlog = page.locator(".project-devlog")
    expect(devlog.locator(f"h3:has-text('{marker}')")).to_be_visible()


def test_devlog_shows_author_info(alice):
    """Author avatar, name and level appear on devlog posts."""
    page, _ = alice
    slug, project_uid, owner_uid = _seed_project()

    marker = f"auth-dl-{uuid4().hex[:8]}"
    _seed_project_post(project_uid, owner_uid, 0, title=marker)

    page.goto(f"{BASE_URL}/projects/{slug}", wait_until="domcontentloaded")

    post_card = page.locator(".project-devlog .post-card").first
    expect(post_card.locator(".post-header")).to_be_visible()
    expect(post_card.locator(".post-author-link")).to_be_visible()
    expect(post_card.locator(".post-time")).to_be_visible()


def test_devlog_shows_vote_and_comment_buttons(alice):
    """Devlog post renders vote buttons and comment count."""
    page, _ = alice
    slug, project_uid, owner_uid = _seed_project()

    marker = f"action-dl-{uuid4().hex[:8]}"
    _seed_project_post(project_uid, owner_uid, 0, title=marker)

    page.goto(f"{BASE_URL}/projects/{slug}", wait_until="domcontentloaded")

    post_card = page.locator(".project-devlog .post-card").first
    expect(post_card.locator(".post-action-btn.vote-up")).to_be_visible()
    expect(post_card.locator(".post-action-btn.vote-down")).to_be_visible()
    expect(post_card.locator(".post-vote-count")).to_be_visible()
    expect(post_card.locator("form[action*='/posts/delete/']")).to_be_visible()


def test_devlog_load_more_appears_with_many_posts(alice):
    """More than PAGE_SIZE posts produces a Load More link."""
    from devplacepy.database.pagination import PAGE_SIZE

    page, _ = alice
    slug, project_uid, owner_uid = _seed_project()

    count = PAGE_SIZE + 1
    for i in range(count):
        _seed_project_post(project_uid, owner_uid, i, title=f"loadmore-{i}")

    page.goto(f"{BASE_URL}/projects/{slug}", wait_until="domcontentloaded")

    devlog = page.locator(".project-devlog")
    expect(devlog.locator(".post-card")).to_have_count(PAGE_SIZE)
    expect(devlog.locator(".load-more-wrap")).to_be_visible()


def test_devlog_guest_sees_devlog_section(app_server):
    """Unauthenticated visitors can see the devlog section."""
    import requests

    slug, _, _ = _seed_project()

    r = requests.get(f"{BASE_URL}/projects/{slug}")
    assert r.status_code == 200, r.text[:200]

    assert "No devlog posts yet." in r.text
    assert 'class="project-devlog"' in r.text


def test_devlog_multiple_posts_order(alice):
    """Posts appear newest-first in the devlog."""
    page, _ = alice
    slug, project_uid, owner_uid = _seed_project()

    markers = []
    for i in range(3):
        marker = f"order-{i}-{uuid4().hex[:8]}"
        markers.append(marker)
        _seed_project_post(project_uid, owner_uid, i, title=marker)

    page.goto(f"{BASE_URL}/projects/{slug}", wait_until="domcontentloaded")

    titles = page.locator(".project-devlog .post-card .post-title")
    expect(titles).to_have_count(3)
    first_text = titles.nth(0).inner_text()
    assert markers[-1] == first_text, (
        f"Expected newest post first: {markers[-1]}, got: {first_text}"
    )


def test_project_stats_card_visible(alice):
    """The sidebar Stats card shows stars, updates, comments, files, forks."""
    page, _ = alice
    slug, project_uid, owner_uid = _seed_project()
    _seed_project_post(project_uid, owner_uid, 0)

    page.goto(f"{BASE_URL}/projects/{slug}", wait_until="domcontentloaded")

    stats = page.locator(".project-stats")
    expect(stats).to_be_visible()
    expect(stats.locator(".project-stat")).to_have_count(5)
    expect(stats.locator(".project-stat:has-text('update')")).to_contain_text("1")


def test_owner_post_update_button_opens_preset_composer(alice):
    """The owner's Post update button opens the composer preselected to this project."""
    page, _ = alice
    _create_project_ui(page, f"Composer Project {uuid4().hex[:6]}")

    button = page.locator(".project-devlog-post-btn")
    expect(button).to_be_visible()
    button.click()

    modal = page.locator("#create-post-modal")
    expect(modal).to_be_visible()
    expect(modal.locator("input[name='topic'][value='devlog']")).to_be_checked()
    selected = modal.locator("#project_uid").input_value()
    assert selected != "", "Expected the project preselected in the composer"


def test_guest_sees_no_post_update_button(app_server):
    """Guests and non-owners get no Post update control."""
    import requests

    slug, _, _ = _seed_project()
    r = requests.get(f"{BASE_URL}/projects/{slug}")
    assert r.status_code == 200
    assert "project-devlog-post-btn" not in r.text
