"""Portable synthetic encrypted-file compatibility study.

Run ``python reproduce.py`` from this directory.  The script uses only public
dummy content and local open-source parsers.  Optional formats are recorded as
``not_run`` when their creator/parser is unavailable; no external fixture is
downloaded and no production application is imported.
"""

from __future__ import annotations

import argparse
import hashlib
import importlib.metadata
import io
import json
import os
import shutil
import socket
import struct
import subprocess
import sys
import tempfile
import time
import zlib
import zipfile
from datetime import datetime, timezone
from pathlib import Path
from typing import Any, Callable


ROOT = Path(__file__).resolve().parent
PASSWORD = "demo-public-2026!"
OWNER_PASSWORD = "demo-owner-2026!"
WRONG_PASSWORD = "wrong-public-2026!"
PUBLIC_TEXT = (
    b"Synthetic public compatibility fixture.\n"
    b"No customer data, secrets, or production identifiers are present.\n"
)
PUBLIC_MEMBER = "public_content.txt"


def now_utc() -> str:
    return datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")


def sha256_file(path: Path) -> str:
    digest = hashlib.sha256()
    with path.open("rb") as handle:
        for chunk in iter(lambda: handle.read(1024 * 1024), b""):
            digest.update(chunk)
    return digest.hexdigest()


def sha256_bytes(value: bytes) -> str:
    return hashlib.sha256(value).hexdigest()


def package_version(name: str) -> str | None:
    try:
        return importlib.metadata.version(name)
    except importlib.metadata.PackageNotFoundError:
        return None


_ZIP_CRC_TABLE: list[int] = []
for _seed in range(256):
    _item = _seed
    for _ in range(8):
        _item = (_item >> 1) ^ (0xEDB88320 if _item & 1 else 0)
    _ZIP_CRC_TABLE.append(_item & 0xFFFFFFFF)


def zip_crc_update(value: int, byte_value: int) -> int:
    return ((value >> 8) ^ _ZIP_CRC_TABLE[(value ^ byte_value) & 0xFF]) & 0xFFFFFFFF


class ZipCrypto:
    def __init__(self, password: bytes) -> None:
        self.keys = [0x12345678, 0x23456789, 0x34567890]
        for byte_value in password:
            self.update(byte_value)

    def update(self, byte_value: int) -> None:
        self.keys[0] = zip_crc_update(self.keys[0], byte_value)
        self.keys[1] = (self.keys[1] + (self.keys[0] & 0xFF)) & 0xFFFFFFFF
        self.keys[1] = (self.keys[1] * 134775813 + 1) & 0xFFFFFFFF
        self.keys[2] = zip_crc_update(self.keys[2], self.keys[1] >> 24)

    def encrypt(self, byte_value: int) -> int:
        key = self.keys[2] | 2
        output = byte_value ^ (((key * (key ^ 1)) >> 8) & 0xFF)
        self.update(byte_value)
        return output


def create_zipcrypto(path: Path) -> None:
    filename = PUBLIC_MEMBER.encode("utf-8")
    compressor = zlib.compressobj(level=6, wbits=-15)
    compressed = compressor.compress(PUBLIC_TEXT) + compressor.flush()
    crc = zlib.crc32(PUBLIC_TEXT) & 0xFFFFFFFF
    header = hashlib.sha256(b"lmpp-public-zipcrypto-header").digest()[:11] + bytes([(crc >> 24) & 0xFF])
    state = ZipCrypto(PASSWORD.encode())
    encrypted = bytes(state.encrypt(byte_value) for byte_value in header + compressed)
    dos_time = 0
    dos_date = (2026 - 1980) << 9 | 10 << 5 | 3
    local = struct.pack(
        "<IHHHHHIIIHH", 0x04034B50, 20, 1, 8, dos_time, dos_date,
        crc, len(encrypted), len(PUBLIC_TEXT), len(filename), 0,
    )
    central = struct.pack(
        "<IHHHHHHIIIHHHHHII", 0x02014B50, 20, 20, 1, 8, dos_time,
        dos_date, crc, len(encrypted), len(PUBLIC_TEXT), len(filename),
        0, 0, 0, 0, 0, 0,
    ) + filename
    eocd = struct.pack("<IHHHHIIH", 0x06054B50, 0, 0, 1, 1, len(central), len(local) + len(filename) + len(encrypted), 0)
    path.write_bytes(local + filename + encrypted + central + eocd)


def create_zip_aes(path: Path) -> None:
    import pyzipper

    with pyzipper.AESZipFile(path, "w", compression=pyzipper.ZIP_DEFLATED, encryption=pyzipper.WZ_AES) as archive:
        archive.setpassword(PASSWORD.encode())
        archive.setencryption(pyzipper.WZ_AES, nbits=256)
        archive.writestr(PUBLIC_MEMBER, PUBLIC_TEXT)


def create_sevenzip(path: Path) -> None:
    import py7zr

    with py7zr.SevenZipFile(path, "w", password=PASSWORD, header_encryption=True) as archive:
        archive.writestr(PUBLIC_TEXT, PUBLIC_MEMBER)


def create_pdf(path: Path, user_password: str, owner_password: str, permissions_flag: Any | None = None) -> None:
    from pypdf import PdfWriter

    writer = PdfWriter()
    writer.add_blank_page(width=612, height=792)
    writer.add_metadata({"/Title": "Synthetic public compatibility fixture"})
    encrypt_kwargs: dict[str, Any] = {"user_password": user_password, "owner_password": owner_password, "use_128bit": True}
    if permissions_flag is not None:
        encrypt_kwargs["permissions_flag"] = permissions_flag
    writer.encrypt(**encrypt_kwargs)
    with path.open("wb") as handle:
        writer.write(handle)


UNO_HELPER = r'''
import sys
import time
from pathlib import Path
import uno
from com.sun.star.beans import PropertyValue

def prop(name, value):
    item = PropertyValue()
    item.Name = name
    item.Value = value
    return item

def connect(port):
    local = uno.getComponentContext()
    resolver = local.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", local)
    last = None
    for _ in range(60):
        try:
            return resolver.resolve(f"uno:socket,host=127.0.0.1,port={port};urp;StarOffice.ComponentContext")
        except Exception as exc:
            last = exc
            time.sleep(0.5)
    raise RuntimeError(f"UNO listener did not start: {last}")

def make(context, kind, output, password):
    desktop = context.ServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop", context)
    service = {"docx": "swriter", "xlsx": "scalc", "pptx": "simpress"}[kind]
    document = desktop.loadComponentFromURL("private:factory/" + service, "_blank", 0, ())
    if kind == "docx":
        document.Text.insertString(document.Text.End, "Synthetic public compatibility fixture.\nNo customer data or secrets.\n", False)
        filter_name = "Office Open XML Text"
    elif kind == "xlsx":
        sheet = document.Sheets.getByIndex(0)
        sheet.getCellByPosition(0, 0).String = "Synthetic public compatibility fixture"
        sheet.getCellByPosition(0, 1).String = "No customer data or secrets."
        filter_name = "Calc MS Excel 2007 XML"
    else:
        page = document.getDrawPages().getByIndex(0)
        if page.getCount() > 0:
            try:
                page.getByIndex(0).String = "Synthetic public compatibility fixture"
            except Exception:
                pass
        filter_name = "Impress MS PowerPoint 2007 XML"
    document.storeAsURL(uno.systemPathToFileUrl(str(Path(output).resolve())), (prop("FilterName", filter_name), prop("Password", password), prop("EncryptFile", True)))
    return document

if __name__ == "__main__":
    port = int(sys.argv[1])
    context = connect(port)
    docs = [make(context, kind, output, sys.argv[5]) for kind, output in zip(("docx", "xlsx", "pptx"), sys.argv[2:5])]
    for document in docs:
        try:
            document.close(False)
        except Exception:
            pass
'''


def find_soffice() -> Path | None:
    names = [shutil.which("soffice"), shutil.which("soffice.exe")]
    for variable in ("PROGRAMFILES", "PROGRAMW6432", "PROGRAMFILES(X86)"):
        base = os.environ.get(variable)
        if base:
            names.append(str(Path(base) / "LibreOffice" / "program" / "soffice.exe"))
    names.extend(["/usr/bin/soffice", "/usr/lib/libreoffice/program/soffice"])
    for candidate in names:
        if candidate and Path(candidate).exists():
            return Path(candidate)
    return None


def free_port() -> int:
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
        sock.bind(("127.0.0.1", 0))
        return int(sock.getsockname()[1])


def create_office(out_dir: Path) -> dict[str, Any]:
    soffice = find_soffice()
    lo_python = soffice.parent / ("python.exe" if os.name == "nt" else "python") if soffice else None
    paths = {
        "docx": out_dir / "modern_password_public.docx",
        "xlsx": out_dir / "modern_password_public.xlsx",
        "pptx": out_dir / "modern_password_public.pptx",
    }
    if not soffice or not lo_python or not lo_python.exists():
        return {"status": "not_run", "reason": "LibreOffice UNO runtime unavailable", "paths": paths}
    port = free_port()
    profile = Path(tempfile.mkdtemp(prefix="repro_lo_profile_"))
    helper = profile / "helper.py"
    helper.write_text(UNO_HELPER, encoding="utf-8")
    command = [
        str(soffice), "--headless",
        f"--accept=socket,host=127.0.0.1,port={port};urp;StarOffice.ComponentContext",
        "--norestore", "--nodefault", "--nofirststartwizard", "--nolockcheck",
        f"-env:UserInstallation={profile.as_uri()}",
    ]
    process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
    started = time.perf_counter()
    try:
        completed = subprocess.run(
            [str(lo_python), str(helper), str(port), str(paths["docx"]), str(paths["xlsx"]), str(paths["pptx"]), PASSWORD],
            capture_output=True, text=True, timeout=90, check=False,
        )
        return {
            "status": "tested" if completed.returncode == 0 else "failed",
            "reason": "" if completed.returncode == 0 else "LibreOffice document creation failed",
            "duration_ms": int(round((time.perf_counter() - started) * 1000)),
            "paths": paths,
        }
    except Exception as exc:
        return {"status": "failed", "reason": f"{type(exc).__name__}: {exc}", "paths": paths}
    finally:
        try:
            process.terminate()
            process.wait(timeout=10)
        except Exception:
            try:
                process.kill()
            except Exception:
                pass
        if os.name == "nt":
            subprocess.run(["taskkill", "/PID", str(process.pid), "/T", "/F"], capture_output=True, check=False)
        shutil.rmtree(profile, ignore_errors=True)


def timed_case(name: str, command: str, callback: Callable[[], dict[str, Any] | None], *, not_run: str | None = None) -> dict[str, Any]:
    if not_run:
        return {"name": name, "status": "not_run", "command": command, "duration_ms": 0, "reason": not_run}
    started = time.perf_counter()
    try:
        details = callback() or {}
        return {"name": name, "status": "tested", "command": command, "duration_ms": int(round((time.perf_counter() - started) * 1000)), "details": details}
    except Exception as exc:
        return {"name": name, "status": "failed", "command": command, "duration_ms": int(round((time.perf_counter() - started) * 1000)), "error": f"{type(exc).__name__}: {exc}"}


def member(path: Path, password: str, *, aes: bool) -> bytes:
    if aes:
        import pyzipper

        with pyzipper.AESZipFile(path) as archive:
            return archive.read(PUBLIC_MEMBER, pwd=password.encode())
    with zipfile.ZipFile(path) as archive:
        return archive.read(PUBLIC_MEMBER, pwd=password.encode())


def sevenzip_member(path: Path, password: str, out_dir: Path) -> bytes:
    import py7zr

    target = Path(tempfile.mkdtemp(prefix="sevenzip_check_", dir=str(out_dir)))
    try:
        with py7zr.SevenZipFile(path, "r", password=password) as archive:
            archive.extractall(path=target)
        return (target / PUBLIC_MEMBER).read_bytes()
    finally:
        shutil.rmtree(target, ignore_errors=True)


def pdf_status(path: Path, password: str) -> int:
    from pypdf import PdfReader

    reader = PdfReader(str(path))
    if not reader.is_encrypted:
        raise AssertionError("fixture is not encrypted")
    return int(reader.decrypt(password))


def office_check(path: Path, password: str, expected_prefix: str) -> dict[str, Any]:
    import msoffcrypto

    with path.open("rb") as source:
        office = msoffcrypto.OfficeFile(source)
        if not office.is_encrypted():
            raise AssertionError("fixture is not encrypted")
        office.load_key(password=password)
        output = io.BytesIO()
        office.decrypt(output)
    names = zipfile.ZipFile(io.BytesIO(output.getvalue())).namelist()
    if "[Content_Types].xml" not in names or not any(expected_prefix in name for name in names):
        raise AssertionError("decrypted OOXML package did not contain expected members")
    return {"decrypted_bytes": len(output.getvalue())}


def encryption_metadata(fixture_id: str, path: Path) -> dict[str, Any]:
    compression_names = {0: "stored", 8: "deflate", 12: "bzip2", 14: "lzma"}
    if fixture_id == "zipcrypto":
        with zipfile.ZipFile(path) as archive:
            info = archive.infolist()[0]
            return {"container": "ZIP", "cipher": "ZipCrypto", "compression": compression_names.get(info.compress_type, str(info.compress_type)), "encrypted_headers": False}
    if fixture_id == "zip_aes256":
        import pyzipper

        with pyzipper.AESZipFile(path) as archive:
            info = archive.infolist()[0]
            strength = getattr(info, "wz_aes_strength", None)
            strength_bits = {1: 128, 2: 192, 3: 256}.get(int(strength), None) if strength else None
            return {"container": "ZIP", "cipher": f"WinZip AES-{strength_bits}" if strength_bits else "WinZip AES", "compression": compression_names.get(info.compress_type, str(info.compress_type)), "encrypted_headers": False}
    if fixture_id == "sevenzip_aes":
        import py7zr

        with py7zr.SevenZipFile(path, password=PASSWORD) as archive:
            info = archive.archiveinfo()
            return {"container": "7z", "cipher": "7z AES-256", "compression": "+".join(info.method_names), "encrypted_headers": True}
    if fixture_id.startswith("pdf_"):
        from pypdf import PdfReader

        encrypt = PdfReader(str(path)).trailer["/Encrypt"]
        version = int(encrypt.get("/V", 0))
        revision = int(encrypt.get("/R", 0))
        permissions = int(encrypt.get("/P", 0))
        return {"container": "PDF Standard Security Handler", "algorithm": "RC4-128" if version == 2 and revision == 3 else f"PDF V{version}/R{revision}", "V": version, "R": revision, "key_length_bits": int(encrypt.get("/Length", 0)), "permissions_P": permissions, "permissions_profile": "print_only" if permissions == 4 else "default_or_other", "open_password_required": fixture_id == "pdf_open"}
    if fixture_id in {"docx", "xlsx", "pptx"}:
        import msoffcrypto

        with path.open("rb") as source:
            office = msoffcrypto.OfficeFile(source)
            info = office.__dict__.get("info", {})
        header = info.get("header", {})
        alg_id = int(header.get("algId", 0))
        hash_id = int(header.get("algIdHash", 0))
        cipher = {0x660E: "AES-128-CBC", 0x660F: "AES-192-CBC", 0x6610: "AES-256-CBC"}.get(alg_id, f"algId 0x{alg_id:04x}")
        digest = {0x8004: "SHA-1", 0x800C: "SHA-512"}.get(hash_id, f"algIdHash 0x{hash_id:04x}")
        return {"container": "OOXML Standard Encryption", "type": info.get("type", "unknown"), "cipher": cipher, "hash": digest, "key_length_bits": int(header.get("keySize", 0)), "alg_id": f"0x{alg_id:04x}", "alg_id_hash": f"0x{hash_id:04x}"}
    return {}


def main() -> int:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--out", type=Path, default=ROOT / "artifacts", help="task-local output directory")
    args = parser.parse_args()
    out_dir = args.out.resolve()
    if out_dir.exists():
        shutil.rmtree(out_dir, ignore_errors=True)
    out_dir.mkdir(parents=True, exist_ok=True)

    files: dict[str, Path] = {
        "zipcrypto": out_dir / "zipcrypto_public.zip",
        "zip_aes256": out_dir / "zip_aes256_public.zip",
        "sevenzip_aes": out_dir / "sevenzip_aes_public.7z",
        "pdf_open": out_dir / "pdf_open_password_public.pdf",
        "pdf_owner_only": out_dir / "pdf_owner_only_public.pdf",
    }
    profiles = {
        "zipcrypto": ("archive", "ZIP ZipCrypto", "zipcrypto"),
        "zip_aes256": ("archive", "ZIP WinZip AES-256", "zipaes"),
        "sevenzip_aes": ("archive", "7z AES-256 with encrypted headers", "sevenzip"),
        "pdf_open": ("pdf", "PDF open/user password (RC4-128 via pypdf)", "pdf_open"),
        "pdf_owner_only": ("pdf", "PDF owner-only password with empty user password", "pdf_owner"),
        "docx": ("office", "modern OOXML DOCX password encryption", "docx"),
        "xlsx": ("office", "modern OOXML XLSX password encryption", "xlsx"),
        "pptx": ("office", "modern OOXML PPTX password encryption", "pptx"),
    }
    creation: dict[str, dict[str, Any]] = {}
    for key, maker in (("zipcrypto", create_zipcrypto), ("zip_aes256", create_zip_aes), ("sevenzip_aes", create_sevenzip)):
        started = time.perf_counter()
        try:
            maker(files[key])
            creation[key] = {"status": "tested", "duration_ms": int(round((time.perf_counter() - started) * 1000))}
        except ImportError as exc:
            creation[key] = {"status": "not_run", "reason": f"optional package unavailable: {exc.name}"}
        except Exception as exc:
            creation[key] = {"status": "failed", "reason": f"{type(exc).__name__}: {exc}"}
    for key, user, owner in (("pdf_open", PASSWORD, OWNER_PASSWORD), ("pdf_owner_only", "", PASSWORD)):
        started = time.perf_counter()
        try:
            permissions_flag = None
            if key == "pdf_owner_only":
                from pypdf.constants import UserAccessPermissions

                permissions_flag = UserAccessPermissions.PRINT
            create_pdf(files[key], user, owner, permissions_flag)
            creation[key] = {"status": "tested", "duration_ms": int(round((time.perf_counter() - started) * 1000))}
        except ImportError as exc:
            creation[key] = {"status": "not_run", "reason": f"optional package unavailable: {exc.name}"}
        except Exception as exc:
            creation[key] = {"status": "failed", "reason": f"{type(exc).__name__}: {exc}"}
    office = create_office(out_dir)
    for key, path in office.get("paths", {}).items():
        files[key] = path
        creation[key] = {key2: value for key2, value in office.items() if key2 != "paths"}

    fixtures: list[dict[str, Any]] = []
    for key, path in files.items():
        family, profile, verify = profiles[key]
        item: dict[str, Any] = {"id": key, "file": path.name, "family": family, "profile": profile, "artifact_license": "CC0-1.0-equivalent synthetic content", "tests": []}
        if not path.exists():
            item.update({"sha256": None, "encryption_metadata": {}, "positive_verified": False, "negative_rejected": False, "result": "not_run"})
            item["tests"].append(timed_case("all_fixture_tests", "python reproduce.py", lambda: {}, not_run="fixture creator did not produce an artifact"))
            item["creation"] = creation[key]
            fixtures.append(item)
            continue
        item["sha256"] = sha256_file(path)
        try:
            item["encryption_metadata"] = encryption_metadata(key, path)
        except Exception as exc:
            item["encryption_metadata"] = {"metadata_status": "not_run", "metadata_reason": type(exc).__name__}
        if verify == "zipcrypto":
            item["tests"].append(timed_case("correct_password_local_parser", "zipfile.ZipFile.read(pwd=PUBLIC_PASSWORD)", lambda p=path: {"content_sha256": sha256_bytes(member(p, PASSWORD, aes=False))} if member(p, PASSWORD, aes=False) == PUBLIC_TEXT else (_ for _ in ()).throw(AssertionError("content mismatch"))))
            def wrong_zip(p=path):
                try:
                    member(p, WRONG_PASSWORD, aes=False)
                except Exception as exc:
                    return {"rejected_error_type": type(exc).__name__}
                raise AssertionError("wrong password was accepted")
            item["tests"].append(timed_case("incorrect_password_rejected", "zipfile.ZipFile.read(pwd=WRONG_PASSWORD)", wrong_zip))
        elif verify == "zipaes":
            available = package_version("pyzipper")
            item["tests"].append(timed_case("correct_password_local_parser", "pyzipper.AESZipFile.read(pwd=PUBLIC_PASSWORD)", lambda p=path: {"content_sha256": sha256_bytes(member(p, PASSWORD, aes=True))} if member(p, PASSWORD, aes=True) == PUBLIC_TEXT else (_ for _ in ()).throw(AssertionError("content mismatch")), not_run=None if available else "pyzipper is not installed"))
            def wrong_aes(p=path):
                try:
                    member(p, WRONG_PASSWORD, aes=True)
                except Exception as exc:
                    return {"rejected_error_type": type(exc).__name__}
                raise AssertionError("wrong password was accepted")
            item["tests"].append(timed_case("incorrect_password_rejected", "pyzipper.AESZipFile.read(pwd=WRONG_PASSWORD)", wrong_aes, not_run=None if available else "pyzipper is not installed"))
        elif verify == "sevenzip":
            available = package_version("py7zr")
            item["tests"].append(timed_case("correct_password_local_parser", "py7zr.SevenZipFile.extractall(password=PUBLIC_PASSWORD)", lambda p=path: {"content_sha256": sha256_bytes(sevenzip_member(p, PASSWORD, out_dir))} if sevenzip_member(p, PASSWORD, out_dir) == PUBLIC_TEXT else (_ for _ in ()).throw(AssertionError("content mismatch")), not_run=None if available else "py7zr is not installed"))
            def wrong_seven(p=path):
                try:
                    sevenzip_member(p, WRONG_PASSWORD, out_dir)
                except Exception as exc:
                    return {"rejected_error_type": type(exc).__name__}
                raise AssertionError("wrong password was accepted")
            item["tests"].append(timed_case("incorrect_password_rejected", "py7zr.SevenZipFile.extractall(password=WRONG_PASSWORD)", wrong_seven, not_run=None if available else "py7zr is not installed"))
        elif verify.startswith("pdf"):
            available = package_version("pypdf")
            if verify == "pdf_open":
                item["tests"].append(timed_case("correct_open_password_local_parser", "pypdf.PdfReader.decrypt(PUBLIC_PASSWORD)", lambda p=path: {"decrypt_result": pdf_status(p, PASSWORD)} if pdf_status(p, PASSWORD) > 0 else (_ for _ in ()).throw(AssertionError("correct password rejected")), not_run=None if available else "pypdf is not installed"))
            else:
                item["tests"].append(timed_case("correct_owner_password_local_parser", "pypdf.PdfReader.decrypt(PUBLIC_PASSWORD)", lambda p=path: {"decrypt_result": pdf_status(p, PASSWORD)} if pdf_status(p, PASSWORD) > 0 else (_ for _ in ()).throw(AssertionError("correct owner password rejected")), not_run=None if available else "pypdf is not installed"))
                item["tests"].append(timed_case("empty_open_password_local_parser", "pypdf.PdfReader.decrypt(EMPTY_PASSWORD)", lambda p=path: {"decrypt_result": pdf_status(p, "")} if pdf_status(p, "") > 0 else (_ for _ in ()).throw(AssertionError("empty user password rejected")), not_run=None if available else "pypdf is not installed"))
            def wrong_pdf(p=path):
                result = pdf_status(p, WRONG_PASSWORD)
                if result == 0:
                    return {"decrypt_result": result}
                raise AssertionError("wrong password was accepted")
            item["tests"].append(timed_case("incorrect_password_rejected", "pypdf.PdfReader.decrypt(WRONG_PASSWORD)", wrong_pdf, not_run=None if available else "pypdf is not installed"))
        else:
            available = package_version("msoffcrypto-tool")
            prefix = {"docx": "word/", "xlsx": "xl/", "pptx": "ppt/"}[verify]
            item["tests"].append(timed_case("correct_password_local_parser", "msoffcrypto.OfficeFile.load_key(PUBLIC_PASSWORD)+decrypt(BytesIO)", lambda p=path, prefix=prefix: office_check(p, PASSWORD, prefix), not_run=None if available else "msoffcrypto-tool is not installed"))
            def wrong_office(p=path, prefix=prefix):
                try:
                    office_check(p, WRONG_PASSWORD, prefix)
                except Exception as exc:
                    return {"rejected_error_type": type(exc).__name__}
                raise AssertionError("wrong password was accepted")
            item["tests"].append(timed_case("incorrect_password_rejected", "msoffcrypto.OfficeFile.load_key(WRONG_PASSWORD)", wrong_office, not_run=None if available else "msoffcrypto-tool is not installed"))
        positive = [test for test in item["tests"] if test["name"] != "incorrect_password_rejected"]
        negative = [test for test in item["tests"] if test["name"] == "incorrect_password_rejected"]
        item["positive_verified"] = bool(positive) and all(test["status"] == "tested" for test in positive)
        item["negative_rejected"] = bool(negative) and all(test["status"] == "tested" for test in negative)
        item["result"] = "verified" if item["positive_verified"] and item["negative_rejected"] else "failed"
        item["creation"] = creation[key]
        fixtures.append(item)

    not_run = [{"id": "rar5_creation", "format": "rar", "status": "not_run", "reason": "No local RAR creator was selected; no unknown fixture was downloaded or fabricated."}]
    counts = {"fixtures_total": len(fixtures), "positive_verified": sum(1 for item in fixtures if item.get("positive_verified")), "negative_rejected": sum(1 for item in fixtures if item.get("negative_rejected")), "verified": sum(1 for item in fixtures if item.get("result") == "verified"), "fixtures_with_test_failures": sum(1 for item in fixtures if item.get("result") == "failed"), "not_run_capability_count": len(not_run), "compatibility_test_durations_are_not_recovery_timings": True, "synthetic_successes_are_not_customer_winrate": True}
    results = {"schema_version": "growth-fixture-compatibility-v1", "generated_at_utc": now_utc(), "scope": {"synthetic_only": True, "customer_data": False, "production_api_or_db": False, "payments": False, "hashcat_or_gpu": False, "worker_fleet": False, "test_password_public": True}, "artifact_license": "CC0-1.0-equivalent synthetic public dummy content.", "public_test_passwords": {"primary": PASSWORD, "owner": OWNER_PASSWORD, "wrong_negative_control": WRONG_PASSWORD, "owner_only_user_password": ""}, "tool_versions": {"python": ".".join(str(value) for value in sys.version_info[:3]), "packages": {name: package_version(name) for name in ("pyzipper", "py7zr", "pypdf", "msoffcrypto-tool")}, "libreoffice_discovered": bool(find_soffice())}, "fixtures": fixtures, "not_run": not_run, "counts": counts}
    (ROOT / "results.json").write_text(json.dumps(results, indent=2, ensure_ascii=False) + "\n", encoding="utf-8")
    (ROOT / "verification-results.json").write_text(json.dumps(results, indent=2, ensure_ascii=False) + "\n", encoding="utf-8")
    with zipfile.ZipFile(ROOT / "fixtures.zip", "w", compression=zipfile.ZIP_DEFLATED) as package:
        for item in fixtures:
            path = out_dir / item["file"]
            if path.exists():
                package.write(path, arcname=item["file"])
    for transient in list(out_dir.iterdir()):
        if transient.name.startswith(".~lock"):
            try:
                transient.unlink()
            except OSError:
                pass
    print(json.dumps(counts, indent=2))
    return 1 if counts["fixtures_with_test_failures"] else 0


if __name__ == "__main__":
    raise SystemExit(main())
