"""Package original measured bytes; never include raw dataset files."""

from __future__ import annotations

import gzip
import hashlib
import io
import json
import tarfile
from datetime import datetime, timezone
from pathlib import Path

from tools import benchmark_online_grid_reuse as bench

ROOT = Path(__file__).resolve().parents[1]
SOURCE = ROOT / "outputs/online-grid-reuse-formal-v1"
DESTINATION = ROOT / "docs/assets/online_grid_reuse"
DESTINATION.mkdir(parents=True, exist_ok=True)
ARCHIVE = DESTINATION / "complete-evidence.tar.gz"
if ARCHIVE.exists():
    raise ValueError("never overwrite publication evidence")


def encode(value):
    return (json.dumps(value, indent=2, allow_nan=False) + "\n").encode()


contents = {
    path.relative_to(SOURCE).as_posix(): path.read_bytes()
    for path in sorted(SOURCE.rglob("*")) if path.is_file()
}
contents["schemas/records.schema.json"] = encode(bench.record_schemas()["summary"])
contents["publication/pack.py.txt"] = Path(__file__).read_bytes()
contents["schemas/index.schema.json"] = encode({
    "type": "object", "additionalProperties": False, "required": ["files", "provenance"],
    "properties": {
        "files": {"type": "object", "additionalProperties": {
            "type": "object", "additionalProperties": False, "required": ["size", "sha256"],
            "properties": {"size": {"type": "integer", "minimum": 0},
                           "sha256": {"type": "string", "pattern": "^[0-9a-f]{64}$"}}}},
        "provenance": {"type": "object"},
    },
})
index = {
    "files": {name: {"size": len(data), "sha256": hashlib.sha256(data).hexdigest()}
              for name, data in sorted(contents.items())},
    "provenance": {
        "created_at": datetime.now(timezone.utc).isoformat(),
        "protocol_sha256": bench.base.sha(SOURCE / "protocol.json"),
        "source_commits": bench.base.read(SOURCE / "protocol.json")["commits"],
        "scope": "Six complete fresh workers, both maintained source trees, no raw images or scans",
        "packer_sha256": bench.base.sha(Path(__file__)),
    },
}
contents["index.json"] = encode(index)
with ARCHIVE.open("xb") as output:
    with gzip.GzipFile(filename="", mode="wb", fileobj=output, mtime=0) as compressed:
        with tarfile.open(fileobj=compressed, mode="w") as archive:
            for name, data in sorted(contents.items()):
                member = tarfile.TarInfo(name)
                member.size, member.mode, member.mtime = len(data), 0o644, 0
                archive.addfile(member, io.BytesIO(data))
inventory = {
    "archive": ARCHIVE.name, "size": ARCHIVE.stat().st_size,
    "sha256": bench.base.sha(ARCHIVE), "indexed_files": len(index["files"]),
    "index_sha256": hashlib.sha256(contents["index.json"]).hexdigest(),
    "summary_sha256": bench.base.sha(SOURCE / "summary.json"),
    "provenance": index["provenance"],
}
(DESTINATION / "inventory.json").write_bytes(encode(inventory))
(DESTINATION / "summary.json").write_bytes((SOURCE / "summary.json").read_bytes())
(DESTINATION / "summary.schema.json").write_bytes(encode(bench.record_schemas()["summary"]))
print(json.dumps(inventory, indent=2))
