"""Search audit logging (#31, FRREP-SR / DCI017).

`track_search_event` was implemented but never called from the search views.
These tests lock in that a real search now writes a SearchEvent row, while a
bare landing render (no query, no filters) does not.
"""
from __future__ import annotations

import pytest
from django.test import Client
from django.urls import reverse

from apps.repository.analytics.models import SearchEvent


@pytest.mark.django_db
def test_search_with_query_records_event(public_collection):
    client = Client()
    resp = client.get(reverse("repo_search:search") + "?q=maize")
    assert resp.status_code == 200

    events = SearchEvent.objects.all()
    assert events.count() == 1
    ev = events.first()
    assert ev.query == "maize"
    assert ev.result_count == resp.context["paginator"].count


@pytest.mark.django_db
def test_search_with_only_filters_records_event(public_collection):
    client = Client()
    resp = client.get(
        reverse("repo_search:search") + f"?collection={public_collection.slug}"
    )
    assert resp.status_code == 200
    ev = SearchEvent.objects.get()
    assert ev.query == ""
    assert ev.filters.get("collection") == public_collection.slug


@pytest.mark.django_db
def test_bare_search_landing_records_nothing(public_collection):
    client = Client()
    resp = client.get(reverse("repo_search:search"))
    assert resp.status_code == 200
    assert SearchEvent.objects.count() == 0


@pytest.mark.django_db
def test_advanced_search_records_event(public_collection):
    client = Client()
    resp = client.get(reverse("repo_search:advanced") + "?title=climate")
    assert resp.status_code == 200
    ev = SearchEvent.objects.get()
    assert ev.filters.get("title") == "climate"


@pytest.mark.django_db
def test_advanced_search_landing_records_nothing(public_collection):
    client = Client()
    resp = client.get(reverse("repo_search:advanced"))
    assert resp.status_code == 200
    assert SearchEvent.objects.count() == 0


# ── FRREP-SR012 — Browse's filter panel joins the same search audit trail ──


@pytest.mark.django_db
def test_browse_with_active_filter_records_event(public_collection):
    client = Client()
    resp = client.get(
        reverse("repo_documents:browse") + f"?collection={public_collection.slug}"
    )
    assert resp.status_code == 200
    ev = SearchEvent.objects.get()
    assert ev.query == ""
    assert ev.filters.get("collection") == [public_collection.slug]


@pytest.mark.django_db
def test_bare_browse_landing_records_nothing(public_collection):
    client = Client()
    resp = client.get(reverse("repo_documents:browse"))
    assert resp.status_code == 200
    assert SearchEvent.objects.count() == 0


# ── FRREP-AR011 — search click-through recording ───────────────────────────


@pytest.mark.django_db
def test_search_result_link_carries_search_event_id_and_click_through_is_recorded(
    public_collection,
):
    """A real end-to-end flow: search -> follow the `?se=` result link ->
    the originating SearchEvent picks up `clicked_document` (previously it was
    always None because `record_search_event` was called with
    `clicked_doc=None` and nothing ever updated it after the fact)."""
    from apps.repository.documents.models import Document

    doc = Document.objects.create(
        title="Click-through target",
        collection=public_collection,
        status=Document.Status.PUBLISHED,
        visibility=Document.Visibility.PUBLIC_OPEN,
        public_document_id="AR011-00001",
    )

    client = Client()
    resp = client.get(
        reverse("repo_search:search") + f"?collection={public_collection.slug}"
    )
    assert resp.status_code == 200
    search_event_id = resp.context["search_event_id"]
    assert search_event_id is not None

    # The result card must link with `?se=<search_event_id>`.
    content = resp.content.decode()
    detail_url = reverse("repo_documents:document_detail", kwargs={"uid": doc.document_uid})
    assert f"{detail_url}?se={search_event_id}" in content

    # Following that link attributes the click-through back to the search.
    resp2 = client.get(f"{detail_url}?se={search_event_id}")
    assert resp2.status_code == 200

    ev = SearchEvent.objects.get(pk=search_event_id)
    assert ev.clicked_document_id == doc.pk


@pytest.mark.django_db
def test_document_detail_without_se_param_does_not_touch_search_events(public_collection):
    from apps.repository.documents.models import Document

    doc = Document.objects.create(
        title="No se param",
        collection=public_collection,
        status=Document.Status.PUBLISHED,
        visibility=Document.Visibility.PUBLIC_OPEN,
        public_document_id="AR011-00002",
    )
    event = SearchEvent.objects.create(query="q", result_count=1)

    client = Client()
    resp = client.get(
        reverse("repo_documents:document_detail", kwargs={"uid": doc.document_uid})
    )
    assert resp.status_code == 200
    assert SearchEvent.objects.get(pk=event.pk).clicked_document_id is None


@pytest.mark.django_db
def test_document_detail_with_garbage_se_param_does_not_crash(public_collection):
    from apps.repository.documents.models import Document

    doc = Document.objects.create(
        title="Garbage se",
        collection=public_collection,
        status=Document.Status.PUBLISHED,
        visibility=Document.Visibility.PUBLIC_OPEN,
        public_document_id="AR011-00003",
    )

    client = Client()
    resp = client.get(
        reverse("repo_documents:document_detail", kwargs={"uid": doc.document_uid})
        + "?se=not-a-number"
    )
    assert resp.status_code == 200
