"""FRREP-SR007 — the in-app inline document reader (#32)."""

from __future__ import annotations

import itertools

import pytest
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import Client
from django.urls import reverse

from apps.repository.documents.models import Document

PDF_BYTES = b"%PDF-1.4\n%\xe2\xe3\xcf\xd3\n1 0 obj<</Type/Catalog>>endobj\ntrailer<<>>\n%%EOF\n"
_seq = itertools.count(1)


def _doc(collection, owner, *, visibility, filename="paper.pdf", body=PDF_BYTES):
    return Document.objects.create(
        title="Maize yield under drought",
        abstract="Body.",
        collection=collection,
        document_type=Document.DocumentType.THESIS,
        license_type=Document.License.CC_BY,
        visibility=visibility,
        status=Document.Status.PUBLISHED,
        submitted_by=owner,
        public_document_id=f"RDR-{next(_seq):05d}",
        file=SimpleUploadedFile(filename, body, content_type="application/octet-stream"),
    )


def _read_url(doc):
    return reverse("repo_documents:document_read", kwargs={"uid": doc.document_uid})


@pytest.mark.django_db
def test_public_pdf_reader_renders_for_anonymous(public_collection, manager_user):
    doc = _doc(public_collection, manager_user, visibility=Document.Visibility.PUBLIC_OPEN)
    resp = Client().get(_read_url(doc))
    assert resp.status_code == 200
    assert resp.context["reader_mode"] == "pdf"
    body = resp.content.decode()
    # PDF.js is wired and points at the in-app raw byte stream, not the media URL.
    assert "pdf.min.js" in body
    assert reverse("repo_documents:document_raw", kwargs={"uid": doc.document_uid}) in body


@pytest.mark.django_db
def test_public_pdf_reader_renders_for_authed(public_collection, manager_user, submitter_user):
    doc = _doc(public_collection, manager_user, visibility=Document.Visibility.PUBLIC_OPEN)
    client = Client()
    client.force_login(submitter_user)
    resp = client.get(_read_url(doc))
    assert resp.status_code == 200
    assert resp.context["reader_mode"] == "pdf"


@pytest.mark.django_db
def test_non_pdf_shows_download_fallback(public_collection, manager_user):
    doc = _doc(public_collection, manager_user, visibility=Document.Visibility.PUBLIC_OPEN,
               filename="data.csv", body=b"a,b\n1,2\n")
    resp = Client().get(_read_url(doc))
    assert resp.status_code == 200
    assert resp.context["reader_mode"] == "fallback"
    assert "Preview isn" in resp.content.decode()


@pytest.mark.django_db
def test_restricted_doc_blocks_anonymous_bytes(restricted_collection, manager_user):
    doc = _doc(restricted_collection, manager_user, visibility=Document.Visibility.RESTRICTED)
    # Anonymous can't even open the reader page for a restricted doc.
    assert Client().get(_read_url(doc)).status_code in (302, 403)
    # …and the raw byte stream is hard-blocked too.
    assert Client().get(
        reverse("repo_documents:document_raw", kwargs={"uid": doc.document_uid})
    ).status_code in (302, 403)


@pytest.mark.django_db
def test_authenticated_only_doc_shows_request_access(public_collection, manager_user, submitter_user):
    """A signed-in non-owner who can see the record but not download it gets the
    'Request access' panel — never the bytes."""
    doc = _doc(public_collection, manager_user, visibility=Document.Visibility.AUTHENTICATED)
    client = Client()
    client.force_login(submitter_user)
    resp = client.get(_read_url(doc))
    assert resp.status_code == 200
    assert resp.context["reader_mode"] == "request_access"
    assert "restricted" in resp.content.decode().lower()


@pytest.mark.django_db
def test_reader_records_access_event(public_collection, manager_user):
    from apps.repository.analytics.models import AccessEvent

    doc = _doc(public_collection, manager_user, visibility=Document.Visibility.PUBLIC_OPEN)
    Client().get(_read_url(doc))
    assert AccessEvent.objects.filter(document=doc).count() == 1
