"""Phase 1.3 — SRS-compliant interactive duplicate handling (#6, FRREP-DCI011).

Uploading a byte-identical file surfaces a cancel / new-version / separate-document
choice instead of silently skipping. Each disposition is exercised here.
"""
from __future__ import annotations

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

from apps.repository.documents import services
from apps.repository.documents.models import Document, DocumentVersion

PDF_BYTES = (
    b"%PDF-1.4\n%\xe2\xe3\xcf\xd3\n1 0 obj<</Type/Catalog>>endobj\n"
    b"trailer<<>>\n%%EOF\n"
)


def _existing_document(collection, submitter):
    """Seed one DRAFT document whose file hash the wizard will collide with."""
    return services.ingest_document(
        file=SimpleUploadedFile("orig.pdf", PDF_BYTES, content_type="application/pdf"),
        title="Original maize study",
        collection=collection,
        document_type=Document.DocumentType.THESIS,
        abstract="The first copy.",
        submitted_by=submitter,
    )


def _post_data(collection_pk, *, decision=""):
    return {
        "title": "Maize study (resubmitted)",
        "abstract": "A second copy of the same bytes.",
        "document_type": Document.DocumentType.THESIS,
        "license_type": Document.License.CC_BY,
        "language": "en",
        "year": 2026,
        "collection": collection_pk,
        "authors_text": "Kato, Amina",
        "duplicate_decision": decision,
        "file": SimpleUploadedFile("dup.pdf", PDF_BYTES, content_type="application/pdf"),
    }


@pytest.mark.django_db
def test_duplicate_without_decision_surfaces_choice(public_collection, submitter_user):
    existing = _existing_document(public_collection, submitter_user)
    client = Client()
    client.force_login(submitter_user)

    resp = client.post(
        reverse("repo_documents:submit"), data=_post_data(public_collection.pk)
    )
    assert resp.status_code == 200  # re-renders with the resolution panel
    html = resp.content.decode()
    assert "This file already exists" in html
    assert existing.public_document_id in html
    # No second document was created while awaiting the user's choice.
    assert Document.objects.count() == 1


@pytest.mark.django_db
def test_duplicate_separate_creates_second_document(public_collection, submitter_user):
    _existing_document(public_collection, submitter_user)
    client = Client()
    client.force_login(submitter_user)

    resp = client.post(
        reverse("repo_documents:submit"),
        data=_post_data(public_collection.pk, decision="separate"),
    )
    assert resp.status_code == 302
    assert Document.objects.count() == 2
    assert Document.objects.filter(file_hash=services.compute_file_hash(
        SimpleUploadedFile("x.pdf", PDF_BYTES)
    )).count() == 2


@pytest.mark.django_db
def test_duplicate_version_attaches_to_original(public_collection, submitter_user):
    existing = _existing_document(public_collection, submitter_user)
    client = Client()
    client.force_login(submitter_user)

    resp = client.post(
        reverse("repo_documents:submit"),
        data=_post_data(public_collection.pk, decision="version"),
    )
    assert resp.status_code == 302
    # No new Document — a version is attached to the original instead. The
    # original already carries its initial 1.0 (FRREP-VL004), so attaching the
    # duplicate as a new version (2.0) leaves two DocumentVersion rows.
    assert Document.objects.count() == 1
    versions = DocumentVersion.objects.filter(document=existing).order_by("uploaded_at")
    assert [v.version_number for v in versions] == ["1.0", "2.0"]


@pytest.mark.django_db
def test_duplicate_cancel_aborts(public_collection, submitter_user):
    _existing_document(public_collection, submitter_user)
    client = Client()
    client.force_login(submitter_user)

    resp = client.post(
        reverse("repo_documents:submit"),
        data=_post_data(public_collection.pk, decision="cancel"),
    )
    assert resp.status_code == 200
    assert b"cancelled" in resp.content.lower()
    assert Document.objects.count() == 1
