"""Verify a pinned study archive, extract it safely, and replay saved derivatives.

Requires cryptography in the caller's Python environment. No model, repository
test, network operation, or cleanup is performed. Extraction and result paths
must be fresh. The archive and this helper are checked against external anchors.
"""

from __future__ import annotations

import argparse
import hashlib
import importlib.util
import json
import resource
import tarfile
import time
from pathlib import Path, PurePosixPath

BYTE_BOUND = 512 * 1024**2
SECONDS_BOUND = 1200


def digest(path):
    h = hashlib.sha256()
    with Path(path).open("rb") as stream:
        for block in iter(lambda: stream.read(1024 * 1024), b""):
            h.update(block)
    return h.hexdigest()


def verify_delivery(archive, anchors, destination):
    start = time.monotonic()
    archive, destination = Path(archive), Path(destination)
    if destination.exists() or destination.is_symlink():
        raise ValueError("Extraction destination already exists")
    if digest(__file__) != anchors["helper_sha256"]:
        raise ValueError("Helper differs from the external anchor")
    if (
        archive.stat().st_size != anchors["archive_bytes"]
        or archive.stat().st_size > BYTE_BOUND
    ):
        raise ValueError("Archive size differs or exceeds the bound")
    if digest(archive) != anchors["archive_sha256"]:
        raise ValueError("Archive differs from the external anchor")
    with tarfile.open(archive, "r:") as saved:
        members = saved.getmembers()
        if len(members) > 5000 or sum(m.size for m in members) > BYTE_BOUND:
            raise ValueError("Archive members exceed the extraction bound")
        names = set()
        for m in members:
            name = PurePosixPath(m.name)
            if (
                name.is_absolute()
                or ".." in name.parts
                or not name.parts
                or name.as_posix() != m.name.rstrip("/")
                or m.name.rstrip("/") in names
                or not (m.isfile() or m.isdir())
            ):
                raise ValueError("Unsafe or repeated archive member")
            names.add(m.name.rstrip("/"))
        destination.mkdir()
        for m in members:
            if time.monotonic() - start > SECONDS_BOUND:
                raise TimeoutError("Recipient operation exceeded its declared bound")
            target = destination / m.name
            if m.isdir():
                target.mkdir(parents=True, exist_ok=True)
            else:
                target.parent.mkdir(parents=True, exist_ok=True)
                with saved.extractfile(m) as source, target.open("xb") as output:
                    copied = 0
                    for block in iter(lambda: source.read(1024 * 1024), b""):
                        copied += len(block)
                        if copied > m.size:
                            raise ValueError("Member exceeded its declared size")
                        output.write(block)
                    if copied != m.size:
                        raise ValueError("Member size differs")
    spec = importlib.util.spec_from_file_location(
        "delivered_study_replay", destination / "study/programs/paired_study_replay.py"
    )
    replay = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(replay)
    _, index, inventory = replay.authenticate(
        destination, anchors["delivery_index_sha256"], anchors["signer_fingerprint"]
    )
    if (
        digest(destination / "member-manifest.json")
        != anchors["delivery_inventory_sha256"]
    ):
        raise ValueError("Delivery inventory differs from the external anchor")
    if index["scientific_index_sha256"] != anchors["scientific_index_sha256"]:
        raise ValueError("Scientific index anchor differs")
    result = replay.verify(
        destination / "study",
        anchors["scientific_index_sha256"],
        anchors["signer_fingerprint"],
        seconds=SECONDS_BOUND,
    )
    elapsed = time.monotonic() - start
    if elapsed > SECONDS_BOUND:
        raise TimeoutError("Recipient operation exceeded its declared bound")
    return {
        "status": "passed",
        "archive_sha256": anchors["archive_sha256"],
        "delivery_signature_authenticated": True,
        "all_delivery_members_matched": True,
        "delivery_members": len(inventory),
        "delivery_index_sha256": anchors["delivery_index_sha256"],
        "source_archive": str(archive.resolve()),
        "fresh_extraction": str(destination.resolve()),
        "seconds": elapsed,
        "peak_rss_bytes": resource.getrusage(resource.RUSAGE_SELF).ru_maxrss,
        "scientific_verification": result,
        "new_model_native_calls": 0,
        "network_operations": 0,
        "cleanup_operations": 0,
    }


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("archive", type=Path)
    parser.add_argument("--anchors", type=Path, required=True)
    parser.add_argument("--extract-to", type=Path, required=True)
    parser.add_argument("--output", type=Path, required=True)
    args = parser.parse_args()
    if args.output.exists() or args.output.is_symlink():
        raise ValueError("Output already exists")
    if args.extract_to.resolve() in args.output.resolve().parents:
        raise ValueError("Output must remain outside the signed extraction")
    anchors = json.loads(args.anchors.read_bytes())
    result = verify_delivery(args.archive, anchors, args.extract_to)
    with args.output.open("x") as stream:
        json.dump(result, stream, indent=2, allow_nan=False)
        stream.write("\n")
    print(
        json.dumps({k: v for k, v in result.items() if k != "scientific_verification"})
    )


if __name__ == "__main__":
    main()
