"""Tests for the wiki web UI pages and API."""

from __future__ import annotations

import pytest
from httpx import ASGITransport, AsyncClient

from abreka.models import WikiPage
from abreka.webui.app import create_app
from abreka.wiki import save_wiki_page


@pytest.fixture
def app_client(abreka_project):
    abreka_dir = abreka_project / "abreka"
    app = create_app(abreka_dir)
    transport = ASGITransport(app=app)
    return AsyncClient(transport=transport, base_url="http://test")


def _seed(abreka_dir, slug="alpha", **kwargs):
    page = WikiPage(slug=slug, **{"title": slug, **kwargs})
    save_wiki_page(page, abreka_dir)
    return page


@pytest.mark.anyio
class TestWikiList:
    async def test_empty_state(self, app_client):
        async with app_client as client:
            resp = await client.get("/wiki")
        assert resp.status_code == 200
        assert "No wiki pages match" in resp.text

    async def test_lists_pages(self, app_client, abreka_project):
        abreka_dir = abreka_project / "abreka"
        _seed(abreka_dir, slug="alpha", title="Alpha", summary="aaa", tags=["x"])
        _seed(abreka_dir, slug="beta", title="Beta", summary="bbb", tags=["y"])
        async with app_client as client:
            resp = await client.get("/wiki")
        html = resp.text
        assert "alpha" in html
        assert "beta" in html
        assert "Alpha" in html
        assert "Beta" in html

    async def test_search_filters(self, app_client, abreka_project):
        abreka_dir = abreka_project / "abreka"
        _seed(abreka_dir, slug="alpha", title="Alpha", summary="balance")
        _seed(abreka_dir, slug="beta", title="Beta", summary="other")
        async with app_client as client:
            resp = await client.get("/wiki?q=balance")
        assert "alpha" in resp.text
        assert "beta" not in resp.text.lower().split("alpha")[1]  # crude — beta should not also appear after alpha

    async def test_tag_filter(self, app_client, abreka_project):
        abreka_dir = abreka_project / "abreka"
        _seed(abreka_dir, slug="alpha", title="Alpha", tags=["eda"])
        _seed(abreka_dir, slug="beta", title="Beta", tags=["lit"])
        async with app_client as client:
            resp = await client.get("/wiki?tag=eda")
        html = resp.text
        assert "alpha" in html
        # 'beta' shouldn't appear in the table — but might in tag chips. Check title.
        assert "Beta" not in html


@pytest.mark.anyio
class TestWikiDetail:
    async def test_renders_page(self, app_client, abreka_project):
        abreka_dir = abreka_project / "abreka"
        _seed(
            abreka_dir,
            slug="alpha",
            title="Alpha",
            summary="summary line",
            tags=["x", "y"],
            body="# Alpha\n\nBody text here.",
        )
        async with app_client as client:
            resp = await client.get("/wiki/alpha")
        assert resp.status_code == 200
        html = resp.text
        assert "Alpha" in html
        assert "summary line" in html
        assert "Body text here." in html
        assert "abreka/wiki/pages/alpha.md" in html

    async def test_missing_page_404(self, app_client):
        async with app_client as client:
            resp = await client.get("/wiki/ghost")
        assert resp.status_code == 404


@pytest.mark.anyio
class TestWikiApi:
    async def test_list(self, app_client, abreka_project):
        abreka_dir = abreka_project / "abreka"
        _seed(abreka_dir, slug="alpha", title="Alpha", tags=["x"])
        async with app_client as client:
            resp = await client.get("/api/wiki")
        assert resp.status_code == 200
        data = resp.json()
        assert isinstance(data["pages"], list)
        assert data["pages"][0]["slug"] == "alpha"

    async def test_get_returns_full_page(self, app_client, abreka_project):
        abreka_dir = abreka_project / "abreka"
        _seed(abreka_dir, slug="alpha", title="Alpha", body="A body")
        async with app_client as client:
            resp = await client.get("/api/wiki/alpha")
        assert resp.status_code == 200
        data = resp.json()
        assert data["slug"] == "alpha"
        assert data["body"] == "A body"

    async def test_get_missing_404(self, app_client):
        async with app_client as client:
            resp = await client.get("/api/wiki/ghost")
        assert resp.status_code == 404

    async def test_create_page(self, app_client, abreka_project):
        async with app_client as client:
            resp = await client.post(
                "/api/wiki",
                json={
                    "title": "Dataset balance",
                    "summary": "9/10 uniform",
                    "tags": "eda, dataset",
                    "content": "# DS\nbody",
                },
            )
        assert resp.status_code == 200, resp.text
        data = resp.json()
        assert data["slug"] == "dataset-balance"
        page_path = abreka_project / "abreka" / "wiki" / "pages" / "dataset-balance.md"
        assert page_path.is_file()

    async def test_create_requires_title(self, app_client):
        async with app_client as client:
            resp = await client.post("/api/wiki", json={"content": "x"})
        assert resp.status_code == 400

    async def test_create_duplicate_409(self, app_client, abreka_project):
        abreka_dir = abreka_project / "abreka"
        _seed(abreka_dir, slug="alpha", title="Alpha")
        async with app_client as client:
            resp = await client.post("/api/wiki", json={"title": "alpha"})
        assert resp.status_code == 409

    async def test_update_page(self, app_client, abreka_project):
        abreka_dir = abreka_project / "abreka"
        _seed(abreka_dir, slug="alpha", title="Alpha", body="old")
        async with app_client as client:
            put_resp = await client.put(
                "/api/wiki/alpha",
                json={"title": "Alpha v2", "content": "new", "tags": "a, b"},
            )
            assert put_resp.status_code == 200
            get_resp = await client.get("/api/wiki/alpha")
        data = get_resp.json()
        assert data["title"] == "Alpha v2"
        assert data["body"] == "new"
        assert data["tags"] == ["a", "b"]

    async def test_update_missing_404(self, app_client):
        async with app_client as client:
            resp = await client.put("/api/wiki/ghost", json={"title": "x"})
        assert resp.status_code == 404

    async def test_delete_page(self, app_client, abreka_project):
        abreka_dir = abreka_project / "abreka"
        _seed(abreka_dir, slug="alpha", title="Alpha")
        async with app_client as client:
            resp = await client.delete("/api/wiki/alpha")
        assert resp.status_code == 200
        page_path = abreka_project / "abreka" / "wiki" / "pages" / "alpha.md"
        assert not page_path.is_file()


@pytest.mark.anyio
class TestWikiCardOnConfigPage:
    async def test_card_present(self, app_client):
        async with app_client as client:
            resp = await client.get("/config")
        html = resp.text
        assert "Project Wiki" in html
        assert "/wiki" in html

    async def test_card_shows_count(self, app_client, abreka_project):
        abreka_dir = abreka_project / "abreka"
        _seed(abreka_dir, slug="alpha", title="Alpha")
        _seed(abreka_dir, slug="beta", title="Beta")
        async with app_client as client:
            resp = await client.get("/config")
        assert ">2</strong>" in resp.text or "2 pages" in resp.text


@pytest.mark.anyio
class TestNavLink:
    async def test_dashboard_has_wiki_link(self, app_client):
        async with app_client as client:
            resp = await client.get("/")
        assert "/wiki" in resp.text
        assert ">Wiki<" in resp.text
