# retoor <retoor@molodetz.nl>

import html
import json
import re
import requests
from tests.conftest import BASE_URL
from devplacepy.database import get_table
from devplacepy.docs_api import API_GROUPS
from devplacepy.utils import clear_user_cache
def _configs_by_id(text):
    configs = re.findall(r"data-config='(.*?)'", text, re.S)
    return {
        json.loads(html.unescape(cfg))["id"]: json.loads(html.unescape(cfg))
        for cfg in configs
    }
def _key_role_visibility(username):
    return get_table("users").find_one(username=username)["api_key"]
_author_key = []
def _author():
    # A dedicated Member author so seeding posts never pollutes alice/bob state
    # (notifications, post counts, XP) that other test files assert on.
    if _author_key:
        return _author_key[0]
    name = "rolevis_author"
    requests.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,
    )
    row = get_table("users").find_one(username=name)
    get_table("users").update({"uid": row["uid"], "role": "Member"}, ["uid"])
    _author_key.append(row["api_key"])
    return _author_key[0]
def _seed_post_role_visibility():
    requests.post(
        f"{BASE_URL}/posts/create",
        headers={"X-API-KEY": _author()},
        data={
            "content": "role visibility seed post body text",
            "title": "RoleVis",
            "topic": "random",
        },
    )


def test_docs_layout_has_sidebar(page, app_server):
    page.goto(f"{BASE_URL}/docs/index.html", wait_until="domcontentloaded")
    assert (
        page.locator(
            ".sidebar-card a.sidebar-link[href='/docs/authentication.html']"
        ).count()
        == 1
    )


def test_docs_auth_examples_use_logged_in_user(alice):
    page, user = alice
    page.goto(f"{BASE_URL}/docs/authentication.html", wait_until="domcontentloaded")
    content = page.content()
    key = get_table("users").find_one(username=user["username"])["api_key"]
    assert key in content
    assert user["username"] in content


def test_docs_widget_code_has_highlight_linenumbers_copy(page, app_server):
    page.goto(f"{BASE_URL}/docs/social-actions.html", wait_until="domcontentloaded")
    panel = page.locator(".code-block pre.code-panel").first
    panel.wait_for(state="visible")
    panel.locator(".code-gutter").first.wait_for(state="attached")
    assert panel.locator(".code-gutter").count() >= 1
    assert panel.locator(".code-copy-btn").count() >= 1
    assert panel.locator("code.hljs").count() >= 1
    # switching language tab re-highlights (not left as plain text)
    page.locator(".code-block .code-tab:has-text('Python')").first.click()
    panel.locator("code.hljs").first.wait_for(state="attached")
    assert panel.locator("code.hljs").count() >= 1


def test_docs_prose_code_has_linenumbers_copy(page, app_server):
    page.goto(f"{BASE_URL}/docs/authentication.html", wait_until="domcontentloaded")
    pre = page.locator(".docs-content pre.code-pre").first
    pre.wait_for(state="visible")
    assert pre.locator(".code-gutter").count() >= 1
    assert pre.locator(".code-copy-btn").count() >= 1
    assert pre.locator("code.hljs").count() >= 1


def test_docs_panel_format_picker_defaults_json(page, app_server):
    page.goto(f"{BASE_URL}/docs/content.html", wait_until="domcontentloaded")
    panel = page.locator(".api-tester").first
    panel.wait_for(state="visible")
    active = panel.locator(".format-option.active").first
    active.wait_for(state="visible")
    assert active.inner_text().strip() == "JSON"
    assert panel.locator(".response-tabs .code-tab:has-text('Expected')").count() == 1
    assert (
        panel.locator(".response-tabs .code-tab:has-text('Live response')").count() == 1
    )
    expected = panel.locator(".response-pane.active").first
    expected.wait_for(state="visible")
    assert expected.locator("pre.response-body code").count() >= 1


def test_docs_panel_html_format_updates_snippet(page, app_server):
    page.goto(f"{BASE_URL}/docs/content.html", wait_until="domcontentloaded")
    panel = page.locator(".api-tester").first
    panel.wait_for(state="visible")
    code = panel.locator("pre.code-panel code").first
    code.wait_for(state="attached")
    assert "application/json" in code.inner_text()
    panel.locator(".format-option:has-text('HTML')").first.click()
    panel.locator("pre.code-panel code").filter(has_text="text/html").first.wait_for(
        timeout=5000
    )


def test_docs_panel_live_send_returns_json(page, app_server):
    page.goto(f"{BASE_URL}/docs/issues.html", wait_until="domcontentloaded")
    panel = page.locator(".api-tester").first
    panel.wait_for(state="visible")
    send = panel.locator(".try-send").first
    send.wait_for(state="visible")
    send.click()
    status = panel.locator(".response-pane.active .response-status").first
    status.wait_for(state="visible", timeout=10000)
    assert status.inner_text().strip().startswith("2")


def test_guest_docs_hide_admin(page, app_server):
    page.goto(f"{BASE_URL}/docs/index.html", wait_until="domcontentloaded")
    assert page.locator("a[href='/docs/admin.html']").count() == 0
    assert page.locator("a[href='/docs/services.html']").count() == 0
    assert requests.get(f"{BASE_URL}/docs/admin.html").status_code == 404
    assert requests.get(f"{BASE_URL}/docs/services.html").status_code == 404


def test_member_docs_hide_admin(bob):
    page, _ = bob
    assert (
        requests.get(
            f"{BASE_URL}/docs/admin.html", headers={"X-API-KEY": _key_role_visibility("bob_test")}
        ).status_code
        == 404
    )
    page.goto(f"{BASE_URL}/docs/index.html", wait_until="domcontentloaded")
    assert page.locator("a[href='/docs/admin.html']").count() == 0


def test_admin_docs_access(alice):
    page, _ = alice
    assert (
        requests.get(
            f"{BASE_URL}/docs/admin.html", headers={"X-API-KEY": _key_role_visibility("alice_test")}
        ).status_code
        == 200
    )
    page.goto(f"{BASE_URL}/docs/index.html", wait_until="domcontentloaded")
    assert page.locator("a[href='/docs/admin.html']").count() >= 1


def test_docs_search_falls_back_to_bm25_when_devii_unavailable(page, app_server):
    # The test server runs with DEVPLACE_DISABLE_SERVICES=1, so agent search is
    # unavailable and the docs search page falls back to the classic BM25 results.
    page.goto(f"{BASE_URL}/docs/search.html?q=authentication", wait_until="domcontentloaded")
    page.locator(".docs-search-bigform").wait_for(state="visible")
    assert page.locator("dp-docs-chat").count() == 0


def test_docs_search_bm25_returns_results(page, app_server):
    page.goto(f"{BASE_URL}/docs/search.html?q=authentication", wait_until="domcontentloaded")
    titles = page.locator(".docs-search-results .docs-search-result-title")
    titles.first.wait_for(state="visible")
    assert titles.count() >= 1


def test_docs_no_floating_autoopen(page, app_server):
    page.goto(f"{BASE_URL}/docs/index.html", wait_until="domcontentloaded")
    assert page.locator("[data-devii-autoopen]").count() == 0
