"""
Tests for INDL-52 — Marketing Home FAQ Section CMS, public route.

Covers the PRD's "Technical Scope" backend bullet:
  - GET /public/faq requires no auth
  - returns settings + only non-deleted items, ordered by sort_order
  - soft-deleted items must NOT appear in the public response

The `indelis_test` DB is migration-managed and already seeded (migration
0059) with 1 `faq_section_settings` row and 7 `faq_items` rows. Per
`tests/conftest.py`, `db_session` only ever `flush()`s within a test and
is rolled back in teardown, so writes made here (via the site-admin API,
to stay black-box) never leak into other tests.
"""
import pytest
from uuid import uuid4

from httpx import AsyncClient
from sqlalchemy.ext.asyncio import AsyncSession

from src.apps.auth.models.user import User
from src.core.security import hash_password


async def _site_admin_token(db: AsyncSession) -> str:
    from src.core.security import create_access_token, build_token_payload

    user = User(
        tenant_id=None,
        email=f"sa.pubfaq.{id(db)}.{uuid4().hex[:8]}@indelis.com",
        password_hash=hash_password("Test1234!"),
        first_name="Site",
        last_name="Admin",
        role="site_admin",
        status="active",
    )
    db.add(user)
    await db.flush()
    return create_access_token(build_token_payload(user))


@pytest.mark.asyncio
async def test_public_faq_requires_no_auth(client: AsyncClient, db_session: AsyncSession):
    resp = await client.get("/api/public/faq")
    assert resp.status_code == 200


@pytest.mark.asyncio
async def test_public_faq_returns_settings_and_ordered_items(
    client: AsyncClient, db_session: AsyncSession
):
    resp = await client.get("/api/public/faq")
    assert resp.status_code == 200
    data = resp.json()["data"]

    settings = data["settings"]
    assert settings is not None
    assert settings["heading"]
    # Public settings shape is deliberately narrow -- no id/timestamps.
    assert set(settings.keys()) == {"heading", "subheading", "intro"}

    items = data["items"]
    assert len(items) >= 7  # migration 0059 seed
    for item in items:
        assert set(item.keys()) == {"id", "question", "answer"}


@pytest.mark.asyncio
async def test_public_faq_excludes_soft_deleted_items(
    client: AsyncClient, db_session: AsyncSession
):
    token = await _site_admin_token(db_session)
    unique_question = f"Will this soft-deleted question {uuid4().hex[:8]} ever show up?"

    created = (
        await client.post(
            "/api/site-admin/faq/items",
            json={"question": unique_question, "answer": "This item will be deleted right after creation."},
            headers={"Authorization": f"Bearer {token}"},
        )
    ).json()["data"]

    # Sanity check: it IS visible on the public endpoint before deletion.
    before = (await client.get("/api/public/faq")).json()["data"]
    assert any(i["question"] == unique_question for i in before["items"])

    del_resp = await client.delete(
        f"/api/site-admin/faq/items/{created['id']}",
        headers={"Authorization": f"Bearer {token}"},
    )
    assert del_resp.status_code == 204

    after = (await client.get("/api/public/faq")).json()["data"]
    assert all(i["question"] != unique_question for i in after["items"])
    assert all(i["id"] != created["id"] for i in after["items"])


@pytest.mark.asyncio
async def test_public_faq_order_matches_sort_order(
    client: AsyncClient, db_session: AsyncSession
):
    token = await _site_admin_token(db_session)
    admin_data = (
        await client.get(
            "/api/site-admin/faq", headers={"Authorization": f"Bearer {token}"}
        )
    ).json()["data"]
    admin_ids_in_order = [i["id"] for i in admin_data["items"]]

    public_data = (await client.get("/api/public/faq")).json()["data"]
    public_ids_in_order = [i["id"] for i in public_data["items"]]

    assert public_ids_in_order == admin_ids_in_order
