"""Check a published synthetic experiment packet with the Python standard library.

Usage: python3 check_results.py
This compares recorded files. It does not run OpenAuditor, authenticate the
original execution, import engine code, call a model, or use the network.
"""

import copy
import hashlib
import json
from pathlib import Path
import sys

HERE = Path(__file__).resolve().parent
RECORDED_REVISION = "6205721f91352039de5ce861c1c94d15d9903c7d"
EXPECTED_INPUT_SHA256 = "f5ec1453238f7cb339f51b4a274fd1728337e312fa679cf9954577bf950026d5"
EXPECTED_ASSERTIONS = {
    "change_vendor_bank": {"change_verified", "no_payment_before_verification"},
    "payment": {"matched", "not_duplicate", "to_vendor_account", "not_to_employee", "after_invoice"},
}


def read(name):
    return json.loads((HERE / name).read_text(encoding="utf-8"))


def require(condition, message):
    if not condition:
        raise ValueError(message)


def comparable(recorded):
    """Exclude only run metadata; retain assertion and item IDs and all facts."""
    result = copy.deepcopy(recorded)
    for item in result["items"]:
        item.pop("id", None)
        item.pop("created_at", None)
    return result


def main():
    request = read("paired-request.json")
    worlds = read("paired-worlds.json")
    first = read("world_a-response.json")
    second = read("world_b-response.json")
    comparison = read("comparison.json")

    serialized = json.dumps(request, sort_keys=True, separators=(",", ":"), ensure_ascii=False)
    digest = hashlib.sha256(serialized.encode("utf-8")).hexdigest()
    require(digest == EXPECTED_INPUT_SHA256, "The published request has changed.")
    for result in (first, second):
        require(result["input_sha256"] == digest, "A response records a different request hash.")
        require(len(result["items"]) == 2, "Expected two recorded item results.")
        require(result["summary"]["verdicts"] == {"true": 2, "false": 0, "uncertain": 0},
                "The recorded verdict summary has changed.")
    require(comparable(first) == comparable(second), "Recorded responses differ beyond run metadata.")
    require(worlds["synthetic"] is True, "The histories must be labeled synthetic.")
    require(worlds["world_a"]["called_party"] != worlds["world_b"]["called_party"],
            "The two stipulated upstream histories must differ.")

    checks = 0
    seen_types = set()
    for item in first["items"]:
        kind = item["item"]["type"]
        require(kind in EXPECTED_ASSERTIONS and kind not in seen_types, "Unexpected or repeated item type.")
        seen_types.add(kind)
        require(item["verdict"] == "true", "A recorded verdict is not true.")
        require(item["certainty"]["basis"] == "unmeasured", "The recorded certainty basis has changed.")
        require(item["input_sha256"] == digest, "An item records a different request hash.")
        require(item["usage"]["questions_asked"] == 0, "A result records model questions.")
        require(item["usage"]["questions_cached"] == 0, "A result records cached model questions.")
        require({a["id"] for a in item["assertions"]} == EXPECTED_ASSERTIONS[kind],
                "The recorded assertion set has changed.")
        require(all(a["outcome"] == "holds" for a in item["assertions"]),
                "A recorded assertion does not hold.")
        checks += len(item["assertions"])
    require(checks == 7, "Expected seven recorded assertions.")

    require(comparison["synthetic"] is True, "The comparison must be labeled synthetic.")
    require(comparison["engine_revision"] == RECORDED_REVISION, "The recorded revision has changed.")
    require(comparison["same_request_sha256"] == digest, "The comparison records a different hash.")
    require(comparison["same_result_except_run_id_and_timestamp"] is True,
            "The comparison does not record matching results.")
    require(comparison["recorded_model_questions"] == 0, "The comparison records model questions.")
    expected_summary = [
        {"type": item["item"]["type"], "verdict": item["verdict"],
         "certainty": item["certainty"], "assertions": item["assertions"]}
        for item in first["items"]
    ]
    require(comparison["items"] == expected_summary, "The comparison does not match the response files.")
    print("Published packet checked: same request hash; matching recorded responses except run metadata;\n"
          "7 holds; 2 true verdicts; unmeasured certainty; 0 recorded model questions.\n"
          "This checks recorded files only. The engine was not run and its original execution was not authenticated.")


if __name__ == "__main__":
    try:
        main()
    except (OSError, ValueError, KeyError, TypeError) as error:
        print(f"Check failed: {error}", file=sys.stderr)
        sys.exit(1)
