#!/usr/bin/env python3
"""Reproduce four export-integrity checks with a supplied aaesverify binary."""

import argparse
import datetime
import hashlib
import json
import os
from pathlib import Path
import platform
import shutil
import subprocess
import sys
import tempfile


def digest(path):
    return hashlib.sha256(path.read_bytes()).hexdigest()


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--verifier", type=Path, required=True)
    parser.add_argument("--export", dest="export_path", type=Path, required=True)
    parser.add_argument("--pubkey", type=Path, required=True)
    parser.add_argument("--output", type=Path)
    args = parser.parse_args()
    inputs = [args.verifier.resolve(), args.export_path.resolve(), args.pubkey.resolve()]
    if args.output and args.output.resolve() in inputs:
        parser.error("the output must not replace an input file")
    for path in inputs:
        if not path.is_file():
            parser.error(f"input file not found: {path}")
    before = [digest(path) for path in inputs]
    report = {
        "schema": "aaes.sample-exercise/v1",
        "performed_at": datetime.datetime.now(datetime.timezone.utc).isoformat(),
        "performed_by": "AAES",
        "exercise_type": "synthetic export integrity; no agent or provider execution",
        "environment": {"os": platform.system(), "architecture": platform.machine(), "python": platform.python_version()},
        "provenance": {"verifier_sha256": before[0], "export_sha256": before[1], "public_key_file_sha256": before[2]},
        "limitations": [
            "Vendor-run exercise of a vendor-supplied synthetic sample; not independent validation.",
            "No approval, credential-bypass, budget, completeness, or provider-outcome control is tested.",
            "A supplied key establishes consistency against that key, not independent key provenance.",
            "Only the specified record-hash edit and wrong-key case are tested; this is not a security audit.",
            "The runner makes no network requests. Network isolation must be established separately by the reviewer.",
        ],
        "checks": [],
    }
    with tempfile.TemporaryDirectory(prefix="aaes-sample-exercise-") as directory:
        scratch = Path(directory)
        binary = scratch / ("aaesverify.exe" if os.name == "nt" else "aaesverify")
        shutil.copyfile(inputs[0], binary)
        binary.chmod(0o700)
        identity = subprocess.run([str(binary), "--version"], capture_output=True, text=True, timeout=15, check=True)
        report["verifier_identity"] = identity.stdout.strip()
        records = [json.loads(line) for line in inputs[1].read_text().splitlines() if line.strip()]
        entry = next(record for record in records if record.get("type") == "entry")
        value = entry["record_hash"]
        entry["record_hash"] = ("b" if value[0] == "a" else "a") + value[1:]
        tampered = scratch / "tampered.jsonl"
        tampered.write_text("".join(json.dumps(record, separators=(",", ":")) + "\n" for record in records))
        wrong_key = scratch / "wrong-key.txt"
        wrong_key.write_text("00" * 32 + "\n")
        cases = [
            ("unchanged", inputs[1], inputs[2], [], 0, {"ok": True, "chain_ok": True, "root_ok": True, "signature_ok": True}),
            ("edited-record-hash", tampered, inputs[2], [], 1, {"ok": False, "chain_ok": False, "root_ok": False}),
            ("wrong-public-key", inputs[1], wrong_key, [], 1, {"ok": False, "signature_ok": False}),
            ("require-independent", inputs[1], inputs[2], ["--require-independent"], 1,
             {"ok": False, "independent_witnesses": 0, "timestamps_independent": 0}),
        ]
        for name, export, key, extra, expected_exit, expected_fields in cases:
            result = subprocess.run([str(binary), "--export", str(export), "--pubkey", str(key), "--json", *extra],
                                    capture_output=True, text=True, timeout=15, check=False)
            try:
                actual = json.loads(result.stdout)
            except json.JSONDecodeError:
                actual = {"unparsed_stdout": result.stdout}
            matches = result.returncode == expected_exit and all(actual.get(field) == value for field, value in expected_fields.items())
            report["checks"].append({"id": name, "expected_exit_code": expected_exit, "expected_fields": expected_fields,
                                     "actual_exit_code": result.returncode, "actual": actual, "stderr": result.stderr,
                                     "matches_expectation": matches})
    report["original_inputs_unchanged"] = before == [digest(path) for path in inputs]
    report["all_expectations_met"] = report["original_inputs_unchanged"] and all(check["matches_expectation"] for check in report["checks"])
    serialized = json.dumps(report, indent=2) + "\n"
    if args.output:
        args.output.write_text(serialized)
    else:
        sys.stdout.write(serialized)
    return 0 if report["all_expectations_met"] else 1


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