import argparse
import json


# Returns an array of the violations in a SARIF file generated by datadog-static-analyzer
def parse_file(file_path):
    try:
        with open(file_path, "r") as file:
            data = json.loads(file.read())
            return data["runs"][0]["results"]
    except Exception as e:
        print(f"Error: couldn't parse {file_path} ({type(e).__name__}: {e})")
        exit(1)


# Converts an object to a JSON string, ensuring that the keys are sorted
def stringify(object):
    return json.dumps(object, sort_keys=True)


# Formats a set of SARIF violations as human-scannable, valid JSON
def pretty_format(set):
    return "[\n" + "\n,\n".join(s for s in set) + "\n]"


arg_parser = argparse.ArgumentParser(
    description="Prints the difference between the violations reported by two SARIF files",
)
arg_parser.add_argument("file_a", help="The path to the first file to compare")
arg_parser.add_argument("file_b", help="The path to the second file to compare")
arg_parser.add_argument(
    "--check",
    help="Exit with a non-zero exit code if differences are found",
    action="store_true",
)
cli_args = arg_parser.parse_args()

file_path_a = cli_args.file_a
file_path_b = cli_args.file_b
parsed_a = parse_file(file_path_a)
parsed_b = parse_file(file_path_b)

set_a = set(stringify(item) for item in parsed_a)
set_b = set(stringify(item) for item in parsed_b)

diff_1 = set_a.difference(set_b)
diff_2 = set_b.difference(set_a)

count_1 = len(diff_1)
print(
    f"{count_1} violation{'s' if count_1 != 1 else ''} in {file_path_a} but not in {file_path_b}{':' if count_1 else ''}"
)
if count_1 > 0:
    print("-----------------------")
    print(pretty_format(diff_1))

print("\n")

count_2 = len(diff_2)
print(
    f"{count_2} violation{'s' if count_2 != 1 else ''} in {file_path_b} but not in {file_path_a}{':' if count_2 else ''}"
)
if count_2 > 0:
    print("-----------------------")
    print(pretty_format(diff_2))

if cli_args.check and (count_1 > 0 or count_2 > 0):
    exit(1)
