"""Layer-3 subprocess-isolated probe tests.

The bomb-guard cap is exercised against `_run_probe` directly (in-process,
where a monkeypatch on the module constant takes effect) — the real probe
runs in a subprocess that re-imports the module, so a parent-process
monkeypatch wouldn't reach the spawned interpreter.
"""

import zipfile
from pathlib import Path

from backend.app.utils import safe_probe


def _zip(path, entries):
    with zipfile.ZipFile(path, "w") as zf:
        for name, data in entries.items():
            zf.writestr(name, data)


def test_probe_archive_valid_zip(tmp_path):
    z = tmp_path / "ok.zip"
    _zip(z, {"a.jpg": b"hello", "b.png": b"world"})
    res = safe_probe.probe_archive(z)
    assert res.ok is True
    assert res.crashed is False


def test_probe_archive_corrupt_zip_clean_rejection(tmp_path):
    z = tmp_path / "broken.zip"
    z.write_bytes(b"PK\x03\x04 not really a zip past here")
    res = safe_probe.probe_archive(z)
    assert res.ok is False
    # Corrupt-but-handled (zipfile raises BadZipFile in the child) — a
    # clean rejection, not a hard crash.
    assert res.crashed is False
    assert res.reason


def test_inspect_archive_reports_size_and_clean_integrity(tmp_path):
    z = tmp_path / "sized.zip"
    _zip(z, {"a.txt": b"x" * 100, "b.txt": b"y" * 50})
    total, bad = safe_probe._inspect_archive(z)
    assert total == 150
    assert bad is None


def test_inspect_archive_detects_misnamed_zip(tmp_path):
    """A zip with a mangled / extension-less name (Patreon URL-blob attachment)
    is still bomb-guarded + integrity-tested via magic-byte detection."""
    z = tmp_path / "01_https___www.patreon.com_media-u_v3_131083093"
    _zip(z, {"a.txt": b"x" * 100})
    total, bad = safe_probe._inspect_archive(z)
    assert total == 100
    assert bad is None


def test_run_probe_bomb_guard(tmp_path, monkeypatch):
    """In-process call to _run_probe so the monkeypatched cap takes effect.
    The public probe_archive runs in a subprocess which re-imports the
    module and wouldn't see the patched constant."""
    monkeypatch.setattr(safe_probe, "MAX_ARCHIVE_UNCOMPRESSED_BYTES", 10)
    z = tmp_path / "bomb.zip"
    _zip(z, {"big.txt": b"x" * 5000})  # 5000 uncompressed > 10-byte cap
    status, detail = safe_probe._run_probe(str(z))
    assert status == "error"
    assert "bomb-guard cap" in detail


def test_probe_video_non_video_is_not_ok(tmp_path):
    """A text file is not a decodable video. Whether ffprobe is present
    (returncode != 0) or absent (OSError → 'unavailable'), the result is
    ok=False. We don't assert on crashed/reason so the test is robust to
    ffprobe presence in CI."""
    f = tmp_path / "nope.txt"
    f.write_text("definitely not a video container")
    res = safe_probe.probe_video(f)
    assert res.ok is False
