"""
GET /api/public/news/{slug} — the endpoint the public NewsDetailPage
actually calls — must increment views_count on read. It never did:
the only increment lived in a sibling GET /news/{post_id} (UUID) route
registered AFTER the str-typed slug route, so FastAPI's str param always
matched first and the increment endpoint was dead/unreachable code.
"""
import pytest
from httpx import AsyncClient
from sqlalchemy.ext.asyncio import AsyncSession

from src.apps.news.models.news_post import NewsPost

TENANT_HDR = "X-Tenant-ID"
NEWS_URL = "/api/public/news"


async def _make_post(db: AsyncSession, tenant_id, **overrides) -> NewsPost:
    fields = {
        "title": "Plot on discount",
        "slug": "plot-on-discount",
        "category": "Heritage",
        "excerpt": "10% discount this week",
        "status": "published",
        "views_count": 0,
    }
    fields.update(overrides)
    post = NewsPost(tenant_id=tenant_id, **fields)
    db.add(post)
    await db.flush()
    return post


@pytest.mark.asyncio
async def test_get_by_slug_increments_views_count(
    client: AsyncClient, db_session: AsyncSession, test_account,
):
    post = await _make_post(db_session, test_account.id)
    await db_session.flush()

    resp = await client.get(f"{NEWS_URL}/{post.slug}", headers={TENANT_HDR: str(test_account.id)})
    assert resp.status_code == 200, resp.text

    await db_session.refresh(post)
    assert post.views_count == 1

    resp2 = await client.get(f"{NEWS_URL}/{post.slug}", headers={TENANT_HDR: str(test_account.id)})
    assert resp2.status_code == 200
    await db_session.refresh(post)
    assert post.views_count == 2


@pytest.mark.asyncio
async def test_get_by_id_fallback_also_increments_views_count(
    client: AsyncClient, db_session: AsyncSession, test_account,
):
    """The slug endpoint also accepts a raw id (fallback used when a post
    has no slug) — same increment must apply there too."""
    post = await _make_post(db_session, test_account.id, slug=None)
    await db_session.flush()

    resp = await client.get(f"{NEWS_URL}/{post.id}", headers={TENANT_HDR: str(test_account.id)})
    assert resp.status_code == 200, resp.text

    await db_session.refresh(post)
    assert post.views_count == 1


@pytest.mark.asyncio
async def test_unpublished_post_not_found_and_not_counted(
    client: AsyncClient, db_session: AsyncSession, test_account,
):
    post = await _make_post(db_session, test_account.id, status="draft")
    await db_session.flush()

    resp = await client.get(f"{NEWS_URL}/{post.slug}", headers={TENANT_HDR: str(test_account.id)})
    assert resp.status_code == 404

    await db_session.refresh(post)
    assert post.views_count == 0


@pytest.mark.asyncio
async def test_list_news_does_not_increment_views_count(
    client: AsyncClient, db_session: AsyncSession, test_account,
):
    """Fetching the list (homepage news strip / News page) must not count
    as a read of any individual post."""
    post = await _make_post(db_session, test_account.id)
    await db_session.flush()

    resp = await client.get(NEWS_URL, headers={TENANT_HDR: str(test_account.id)})
    assert resp.status_code == 200

    await db_session.refresh(post)
    assert post.views_count == 0
