"""Check synthetic direct-property sets; this does not grant approvals or permissions."""
import json
from pathlib import Path
from importlib.metadata import version
from rdflib import Graph, Namespace
from pyshacl import validate

EX = Namespace("https://example.org/sets/")
SH = Namespace("http://www.w3.org/ns/shacl#")


def main():
    data = json.loads(Path(__file__).with_name("shacl-set-equality-fixtures.json").read_text(encoding="utf-8"))
    observations = []
    for sample in data["samples"]:
        graph = Graph().parse(data=sample["data"], format="turtle")
        expected = set(graph.objects(EX.request, EX.expected))
        actual = set(graph.objects(EX.request, EX.actual))
        results = {}
        components = {}
        for rule, turtle in data["shapes"].items():
            conforms, report, _ = validate(graph, shacl_graph=Graph().parse(data=turtle, format="turtle"),
                                           inference="none", advanced=False)
            results[rule] = bool(conforms)
            components[rule] = sorted({str(c).split("#")[-1] for c in report.objects(None, SH.sourceConstraintComponent)})
        oracle = {"equals": expected == actual, "disjoint": not expected.intersection(actual),
                  "requiredEquals": bool(expected) and bool(actual) and expected == actual}
        assert results == sample["expected"] == oracle, (sample["name"], results, oracle)
        observations.append({"name": sample["name"], "expectedValues": sorted(str(v) for v in expected),
                             "actualValues": sorted(str(v) for v in actual),
                             "missing": sorted(str(v) for v in expected - actual),
                             "extra": sorted(str(v) for v in actual - expected),
                             "overlap": sorted(str(v) for v in expected & actual),
                             "conforms": results, "components": components})
    print(json.dumps({"pyshacl": version("pyshacl"), "rdflib": version("rdflib"),
                      "inference": "none", "advanced": False, "scope": data["scope"],
                      "observations": observations, "pass": True}, ensure_ascii=False, indent=2))


if __name__ == "__main__":
    main()
