"""FRREP-AR006 — report export formats (xlsx/csv/pdf)."""

from __future__ import annotations

import io
import itertools

import pytest

from apps.repository.analytics import services as analytics_services
from apps.repository.analytics.models import DownloadEvent
from apps.repository.documents.models import Author, Document

_seq = itertools.count(1)


def _weasyprint_available() -> bool:
    try:
        import weasyprint  # noqa: F401
    except Exception:  # pragma: no cover - environment-specific
        return False
    return True


def _published(collection, title, **kwargs):
    return Document.objects.create(
        title=title,
        collection=collection,
        status=Document.Status.PUBLISHED,
        visibility=Document.Visibility.PUBLIC_OPEN,
        public_document_id=f"EXP-{next(_seq):05d}",
        **kwargs,
    )


@pytest.mark.django_db
def test_export_report_rejects_unknown_format():
    with pytest.raises(ValueError):
        analytics_services.export_report("usage", "yaml")


@pytest.mark.django_db
def test_export_xlsx_and_csv_still_work(public_collection):
    assert analytics_services.export_report("usage", "xlsx")[:2] == b"PK"  # xlsx = zip
    assert b"Collection" in analytics_services.export_report("compliance", "csv")


@pytest.mark.skipif(not _weasyprint_available(), reason="WeasyPrint native deps missing")
@pytest.mark.django_db
@pytest.mark.parametrize("kind", ["usage", "compliance", "author_impact", "something_unknown"])
def test_export_pdf_returns_valid_pdf_bytes_for_each_kind(kind, public_collection):
    data = analytics_services.export_report(kind, "pdf")
    assert data[:4] == b"%PDF"


@pytest.mark.skipif(not _weasyprint_available(), reason="WeasyPrint native deps missing")
@pytest.mark.django_db
def test_export_pdf_usage_includes_real_download_totals(public_collection):
    doc = _published(public_collection, "Downloaded a lot")
    for _ in range(4):
        DownloadEvent.objects.create(document=doc)

    data = analytics_services.export_report("usage", "pdf")
    assert data[:4] == b"%PDF"
    # Sanity: the underlying data actually reflects the download we recorded.
    stats = analytics_services.get_usage_dashboard()
    assert stats["total_downloads"] >= 4


@pytest.mark.skipif(not _weasyprint_available(), reason="WeasyPrint native deps missing")
@pytest.mark.django_db
def test_export_pdf_author_impact_reuses_get_author_impact(public_collection):
    author = Author.objects.create(first_name="Grace", last_name="Kato")
    doc = _published(public_collection, "Kato's paper")
    doc.authors.add(author)
    DownloadEvent.objects.create(document=doc)

    data = analytics_services.export_report("author_impact", "pdf")
    assert data[:4] == b"%PDF"


# ── FRREP-AR006 — collection export kind + real author_impact xlsx/csv ────


@pytest.mark.django_db
def test_export_xlsx_author_impact_has_real_rows_not_stub(public_collection):
    author = Author.objects.create(first_name="Grace", last_name="Kato")
    doc = _published(public_collection, "Kato's paper for xlsx")
    doc.authors.add(author)
    DownloadEvent.objects.create(document=doc)

    from openpyxl import load_workbook

    data = analytics_services.export_report("author_impact", "xlsx")
    wb = load_workbook(io.BytesIO(data))
    ws = wb.active
    rows = list(ws.iter_rows(values_only=True))
    assert rows[0] == ("Author", "Documents", "Downloads", "Views")
    names = [r[0] for r in rows[1:]]
    assert "Grace Kato" in names


@pytest.mark.django_db
def test_export_csv_author_impact_has_real_rows_not_stub(public_collection):
    author = Author.objects.create(first_name="Grace", last_name="Kato")
    doc = _published(public_collection, "Kato's paper for csv")
    doc.authors.add(author)
    DownloadEvent.objects.create(document=doc)

    data = analytics_services.export_report("author_impact", "csv").decode()
    assert "Grace Kato" in data
    assert data.splitlines()[0] == "Author,Documents,Downloads,Views"


@pytest.mark.django_db
def test_export_xlsx_collection_kind_reports_the_requested_collection(public_collection):
    doc = _published(public_collection, "Collection export doc")
    DownloadEvent.objects.create(document=doc)

    from openpyxl import load_workbook

    data = analytics_services.export_report("collection", "xlsx", slug=public_collection.slug)
    wb = load_workbook(io.BytesIO(data))
    ws = wb.active
    rows = list(ws.iter_rows(values_only=True))
    # Rows are padded to the sheet's widest row (3 cols, from the "Most
    # accessed" table below), so compare on the leading cells only.
    assert any(r[0] == "Collection" and r[1] == public_collection.name for r in rows)


@pytest.mark.django_db
def test_export_csv_collection_kind_reports_the_requested_collection(public_collection):
    doc = _published(public_collection, "Collection export doc csv")
    DownloadEvent.objects.create(document=doc)

    data = analytics_services.export_report("collection", "csv", slug=public_collection.slug).decode()
    assert public_collection.name in data


@pytest.mark.django_db
def test_export_collection_kind_unknown_slug_does_not_crash():
    data = analytics_services.export_report("collection", "csv", slug="does-not-exist")
    assert b"error" in data.lower() or b"Unknown" in data


@pytest.mark.skipif(not _weasyprint_available(), reason="WeasyPrint native deps missing")
@pytest.mark.django_db
def test_export_pdf_collection_kind_returns_valid_pdf(public_collection):
    doc = _published(public_collection, "Collection export doc pdf")
    DownloadEvent.objects.create(document=doc)

    data = analytics_services.export_report("collection", "pdf", slug=public_collection.slug)
    assert data[:4] == b"%PDF"


@pytest.mark.django_db
def test_export_report_view_forwards_slug_for_collection_kind(client, manager_user, public_collection):
    doc = _published(public_collection, "View-forwarded doc")
    DownloadEvent.objects.create(document=doc)

    client.force_login(manager_user)
    response = client.get(
        f"/repository/analytics/export/collection/",
        {"format": "csv", "slug": public_collection.slug},
    )

    assert response.status_code == 200
    assert public_collection.name in response.content.decode()


@pytest.mark.django_db
def test_export_report_view_forwards_by_for_compliance_kind(client, manager_user, public_collection):
    doc = _published(public_collection, "Compliance forwarded doc")

    client.force_login(manager_user)
    response = client.get(
        "/repository/analytics/export/compliance/",
        {"format": "csv", "by": "document_type"},
    )

    assert response.status_code == 200
    assert b"Document type" in response.content
