"""
Tests for the public "Find a loved one" search (GET /api/public/records):
  - flat paginated response shape (data = list, total/page at root)
  - typo-tolerant (trigram) fuzzy matching
  - memorial_slug exposed only for a published memorial
  - visibility gate (only visibility_config='public')
"""
import pytest
from httpx import AsyncClient

TENANT_HDR = "X-Tenant-ID"


async def _make_public_record(db, tenant_id, *, first, last, visibility="public", with_published_memorial=False):
    from src.apps.records.models.record import Record
    from src.apps.memorials.models.memorial import Memorial

    rec = Record(
        tenant_id=tenant_id, first_name=first, last_name=last, visibility_config=visibility
    )
    db.add(rec)
    await db.flush()
    if with_published_memorial:
        slug = f"{first}-{last}".lower().replace("'", "").replace(" ", "-")
        db.add(Memorial(tenant_id=tenant_id, record_id=rec.id, slug=slug, is_published=True))
        await db.flush()
    return rec


@pytest.mark.asyncio
async def test_search_response_is_flat_shape(client: AsyncClient, db_session, test_account):
    await _make_public_record(db_session, test_account.id, first="Patricia", last="OBrien")
    r = await client.get("/api/public/records?name=patricia", headers={TENANT_HDR: str(test_account.id)})
    assert r.status_code == 200
    body = r.json()
    # Flat shape: data is a list, pagination at root (NOT data.items)
    assert isinstance(body["data"], list)
    assert "total" in body and "page" in body and "pages" in body
    assert body["total"] == 1


@pytest.mark.asyncio
async def test_search_is_typo_tolerant(client: AsyncClient, db_session, test_account):
    await _make_public_record(db_session, test_account.id, first="Patricia", last="OBrien")
    # "patrica" is a common misspelling of "Patricia" (not a substring of it)
    r = await client.get("/api/public/records?name=patrica", headers={TENANT_HDR: str(test_account.id)})
    assert r.status_code == 200
    assert r.json()["total"] == 1


@pytest.mark.asyncio
async def test_search_exposes_memorial_slug_when_published(client: AsyncClient, db_session, test_account):
    await _make_public_record(
        db_session, test_account.id, first="Patricia", last="OBrien", with_published_memorial=True
    )
    r = await client.get("/api/public/records?name=patricia", headers={TENANT_HDR: str(test_account.id)})
    item = r.json()["data"][0]
    assert item["memorial_slug"] == "patricia-obrien"


@pytest.mark.asyncio
async def test_search_no_slug_without_memorial(client: AsyncClient, db_session, test_account):
    await _make_public_record(db_session, test_account.id, first="Nomem", last="Orial")
    r = await client.get("/api/public/records?name=nomem", headers={TENANT_HDR: str(test_account.id)})
    assert r.json()["data"][0]["memorial_slug"] is None


@pytest.mark.asyncio
async def test_search_excludes_non_public_records(client: AsyncClient, db_session, test_account):
    await _make_public_record(db_session, test_account.id, first="Hidden", last="Person", visibility="private")
    r = await client.get("/api/public/records?name=hidden", headers={TENANT_HDR: str(test_account.id)})
    assert r.json()["total"] == 0
