#!/usr/bin/env python3
"""Check four synthetic audit-evidence packets using only Python's stdlib.

This checks record consistency. It does not audit code, execute retests,
compile contracts, authenticate documents or contact a blockchain.
The fixture's commit labels and bytecode snapshots are invented teaching data.
"""

import argparse
import hashlib
import json
from pathlib import Path


def digest(text):
    return hashlib.sha256(text.encode("utf-8")).hexdigest()


def runtime_bytes(value):
    if not isinstance(value, str) or not value.startswith("0x"):
        return None
    try:
        result = bytes.fromhex(value[2:])
    except ValueError:
        return None
    return result or None


def check_packet(packet):
    report = packet["report"]
    release = packet["release"]
    scope_reasons = []
    if release["sourceCommit"] != report["finalReviewedCommit"]:
        scope_reasons.append("release_commit_not_final_reviewed_commit")
    expected = report["sourceSha256"]
    actual = {name: digest(text) for name, text in release["sourceFiles"].items()}
    if not expected or expected != actual:
        scope_reasons.append("listed_source_files_or_digests_differ")

    retest_reasons = []
    retests = {item["findingId"]: item for item in packet["retestRecords"]}
    for finding in report["findings"]:
        finding_id = finding["id"]
        retest = retests.get(finding_id)
        if finding["status"] != "resolved":
            retest_reasons.append(f"{finding_id}:not_recorded_as_resolved")
        if not retest:
            retest_reasons.append(f"{finding_id}:retest_record_missing")
            continue
        if retest["commit"] != finding["fixCommit"]:
            retest_reasons.append(f"{finding_id}:retest_commit_differs_from_fix")
        if retest["commit"] != report["finalReviewedCommit"]:
            retest_reasons.append(f"{finding_id}:retest_not_on_final_reviewed_commit")
        if retest["result"] != "pass" or not retest["testCase"]:
            retest_reasons.append(f"{finding_id}:passing_test_record_missing")

    built = runtime_bytes(packet["buildRecord"]["runtimeHex"])
    deployed = runtime_bytes(packet["deploymentRecord"]["runtimeHex"])
    artifact_reasons = []
    if built is None or deployed is None or built != deployed:
        artifact_reasons.append("runtime_bytes_missing_invalid_or_different")
    groups = {
        "scope_commit": scope_reasons,
        "findings_retest": retest_reasons,
        "deployed_artifact": artifact_reasons,
    }
    return {
        "case": packet["id"],
        "checks": {
            name: {"consistent": not reasons, "reasons": reasons}
            for name, reasons in groups.items()
        },
        "runtimeBytesCompared": len(built) if built is not None else 0,
    }


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument(
        "--fixtures", type=Path,
        default=Path(__file__).with_name("fixtures.json"),
    )
    args = parser.parse_args()
    fixture_bytes = args.fixtures.read_bytes()
    fixture = json.loads(fixture_bytes)
    results = [check_packet(packet) for packet in fixture["packets"]]
    consistency = [
        check["consistent"]
        for result in results for check in result["checks"].values()
    ]
    actual_mismatches = {
        result["case"]: [
            name for name, check in result["checks"].items()
            if not check["consistent"]
        ]
        for result in results
    }
    expected_match = actual_mismatches == fixture["expectedMismatches"]
    output = {
        "exercise": "synthetic-audit-evidence-consistency-v1",
        "synthetic": True,
        "fixtureSha256": hashlib.sha256(fixture_bytes).hexdigest(),
        "caseCount": len(results),
        "checksRun": len(consistency),
        "consistentChecks": sum(consistency),
        "mismatchedChecks": len(consistency) - sum(consistency),
        "matchesExpectedControls": expected_match,
        "results": results,
        "limits": fixture["limits"],
    }
    print(json.dumps(output, indent=2, sort_keys=True))
    return 0 if expected_match else 1


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