from pathlib import Path

from PIL import Image
from pypdf import PdfReader

from fixtures.generate_fixtures import make_a4_pdf, make_image_without_metadata, make_password_pdf
from mints_prep.config import EvidenceStampConfig
from mints_prep.models import Classification, FileRecord, FilenameFinding, FormatStatus, PdfFinding
from mints_prep.ui.preview import render_preview, render_preview_with_stamp

_STAMP_CONFIG = EvidenceStampConfig(font_size_pt=14, margin_top_mm=8, margin_right_mm=8)


def _record(path: Path, detected_format: str, pdf_finding: PdfFinding | None = None) -> FileRecord:
    return FileRecord(
        path=path,
        size_bytes=100,
        format_status=FormatStatus.RECORD_READY,
        detected_format=detected_format,
        classification=Classification.A_COMPLIANT,
        filename_finding=FilenameFinding(
            length=len(path.name), exceeds_max_length=False, exceeds_warning_length=False
        ),
        pdf_finding=pdf_finding,
    )


def test_render_preview_returns_image_for_pdf(tmp_path: Path):
    path = make_a4_pdf(tmp_path / "甲001.pdf")

    image = render_preview(_record(path, "PDF"))

    assert isinstance(image, Image.Image)


def test_render_preview_returns_none_for_password_protected_pdf(tmp_path: Path):
    path = make_password_pdf(tmp_path / "甲002.pdf")

    image = render_preview(_record(path, "PDF", pdf_finding=PdfFinding(has_password=True)))

    assert image is None


def test_render_preview_returns_image_for_png(tmp_path: Path):
    path = make_image_without_metadata(tmp_path / "甲003.png")

    image = render_preview(_record(path, "PNG"))

    assert isinstance(image, Image.Image)


def test_render_preview_returns_none_for_audio_video(tmp_path: Path):
    path = tmp_path / "甲004.mp3"
    path.write_bytes(b"fake mp3 content")

    image = render_preview(_record(path, "MP3"))

    assert image is None


def test_render_preview_returns_none_for_missing_file(tmp_path: Path):
    path = tmp_path / "does_not_exist.pdf"

    image = render_preview(_record(path, "PDF"))

    assert image is None


def test_render_preview_respects_max_dimensions(tmp_path: Path):
    path = make_a4_pdf(tmp_path / "甲005.pdf")

    image = render_preview(_record(path, "PDF"), max_width=200, max_height=200)

    assert image.width <= 200
    assert image.height <= 200


def test_render_preview_with_stamp_shows_label_on_pdf(tmp_path: Path):
    path = make_a4_pdf(tmp_path / "甲006 契約書.pdf")

    image = render_preview_with_stamp(_record(path, "PDF"), "甲006", _STAMP_CONFIG)

    assert isinstance(image, Image.Image)


def test_render_preview_with_stamp_does_not_modify_original_pdf(tmp_path: Path):
    path = make_a4_pdf(tmp_path / "甲007 契約書.pdf")
    original_page_count = len(PdfReader(str(path)).pages)
    original_text = PdfReader(str(path)).pages[0].extract_text()

    render_preview_with_stamp(_record(path, "PDF"), "甲007", _STAMP_CONFIG)

    assert len(PdfReader(str(path)).pages) == original_page_count
    assert "甲007" not in original_text
    assert "甲007" not in PdfReader(str(path)).pages[0].extract_text()


def test_render_preview_with_stamp_returns_none_for_password_protected_pdf(tmp_path: Path):
    path = make_password_pdf(tmp_path / "甲008.pdf")

    image = render_preview_with_stamp(
        _record(path, "PDF", pdf_finding=PdfFinding(has_password=True)), "甲008", _STAMP_CONFIG
    )

    assert image is None


def test_render_preview_with_stamp_returns_image_for_png(tmp_path: Path):
    path = make_image_without_metadata(tmp_path / "甲009.png")

    image = render_preview_with_stamp(_record(path, "PNG"), "甲009", _STAMP_CONFIG)

    assert isinstance(image, Image.Image)


def test_render_preview_with_stamp_differs_from_plain_preview(tmp_path: Path):
    path = make_a4_pdf(tmp_path / "甲010 契約書.pdf")
    record = _record(path, "PDF")

    plain = render_preview(record)
    stamped = render_preview_with_stamp(record, "甲010", _STAMP_CONFIG)

    assert plain.tobytes() != stamped.tobytes()
