"""Phase 2.2 — automatic metadata extraction (FRREP-DCI009).

On stage-1 finalize the server reads the file's own embedded properties
(PDF info dict / DOCX core-properties) and returns them as *editable
suggestions* the wizard pre-fills. A metadata-less file yields only the
filesystem facts and never crashes.
"""
from __future__ import annotations

import io

import pytest

from apps.repository.documents import services


def _pdf_with_metadata(tmp_path):
    from pypdf import PdfWriter

    writer = PdfWriter()
    writer.add_blank_page(width=200, height=200)
    writer.add_metadata({"/Title": "Embedded PDF Title", "/Author": "Jane Embedded"})
    path = tmp_path / "with_meta.pdf"
    with path.open("wb") as fh:
        writer.write(fh)
    return path


def _docx_with_metadata(tmp_path):
    from docx import Document as DocxDocument

    doc = DocxDocument()
    doc.core_properties.title = "Embedded DOCX Title"
    doc.core_properties.author = "Otieno Brian"
    doc.add_paragraph("body text")
    path = tmp_path / "with_meta.docx"
    doc.save(str(path))
    return path


def test_extract_pdf_metadata(tmp_path):
    path = _pdf_with_metadata(tmp_path)
    meta = services.extract_file_metadata(path, filename="with_meta.pdf")
    assert meta["title"] == "Embedded PDF Title"
    assert meta["author"] == "Jane Embedded"
    assert meta["filename"] == "with_meta.pdf"
    assert meta["size_bytes"] > 0


def test_extract_docx_metadata(tmp_path):
    path = _docx_with_metadata(tmp_path)
    meta = services.extract_file_metadata(path, filename="with_meta.docx")
    assert meta["title"] == "Embedded DOCX Title"
    assert meta["author"] == "Otieno Brian"


def test_extract_metadataless_file_is_safe(tmp_path):
    path = tmp_path / "plain.txt"
    path.write_bytes(b"just some text, no embedded metadata")
    meta = services.extract_file_metadata(path, filename="plain.txt")
    # No title/author, but the filesystem facts are always present and no crash.
    assert "title" not in meta
    assert "author" not in meta
    assert meta["filename"] == "plain.txt"
    assert meta["size_bytes"] > 0


def test_extract_corrupt_pdf_is_safe(tmp_path):
    path = tmp_path / "broken.pdf"
    path.write_bytes(b"%PDF-1.4 not really a pdf")
    meta = services.extract_file_metadata(path, filename="broken.pdf")
    # Best-effort: corruption is swallowed, filename still returned.
    assert meta["filename"] == "broken.pdf"


@pytest.mark.django_db
def test_staged_upload_returns_metadata(submitter_user, tmp_path):
    from django.core.files.uploadedfile import SimpleUploadedFile
    from django.test import Client
    from django.urls import reverse

    pdf_path = _pdf_with_metadata(tmp_path)
    client = Client()
    client.force_login(submitter_user)
    upload = SimpleUploadedFile(
        "with_meta.pdf", pdf_path.read_bytes(), content_type="application/pdf"
    )
    resp = client.post(reverse("repo_documents:staged_upload"), {"file": upload})
    assert resp.status_code == 200
    payload = resp.json()
    assert payload["metadata"]["title"] == "Embedded PDF Title"
    assert payload["metadata"]["author"] == "Jane Embedded"
