#!/usr/bin/env python3
"""Tests for tools/util.py hash utilities."""

import re
import sys
import unittest
from pathlib import Path

# Add project root to path
sys.path.insert(0, str(Path(__file__).parent.parent))

from tools.util import calculate_hash, calculate_hash_for_new_artifact


class TestCalculateHash(unittest.TestCase):
    """Tests for calculate_hash() function."""

    def test_dict_hash_is_order_insensitive(self):
        """Legacy dict hashing produces same result regardless of key order."""
        dict_a = {"zebra": 1, "apple": 2, "mango": 3}
        dict_b = {"apple": 2, "mango": 3, "zebra": 1}

        # sort_keys=False is default, but dicts have same content
        # With sort_keys=False, order matters - these should differ
        hash_a = calculate_hash(dict_a, exclude_fields=set())
        hash_b = calculate_hash(dict_b, exclude_fields=set())

        # Default behavior preserves insertion order (hashes differ)
        self.assertNotEqual(hash_a, hash_b)

        # With sort_keys=True, order is normalized (hashes match)
        hash_a_sorted = calculate_hash(dict_a, exclude_fields=set(), sort_keys=True)
        hash_b_sorted = calculate_hash(dict_b, exclude_fields=set(), sort_keys=True)
        self.assertEqual(hash_a_sorted, hash_b_sorted)

    def test_hash_output_is_valid_sha256_hex(self):
        """Hash outputs are valid 64-character hexadecimal strings."""
        sha256_pattern = re.compile(r'^[a-f0-9]{64}$')

        # Test string input
        string_hash = calculate_hash("test content")
        self.assertRegex(string_hash, sha256_pattern)

        # Test dict input
        dict_hash = calculate_hash({"key": "value"}, exclude_fields=set())
        self.assertRegex(dict_hash, sha256_pattern)


class TestCalculateHashForNewArtifact(unittest.TestCase):
    """Tests for calculate_hash_for_new_artifact() function."""

    def test_new_artifact_hash_is_deterministic(self):
        """Same artifact data always produces the same hash."""
        artifact = {
            "@context": "https://schema.org",
            "@type": "DigitalDocument",
            "name": "Test Artifact",
            "value": 42
        }

        hash1 = calculate_hash_for_new_artifact(artifact)
        hash2 = calculate_hash_for_new_artifact(artifact)

        self.assertEqual(hash1, hash2)

    def test_new_artifact_hash_ignores_key_order(self):
        """New artifact hashing is order-insensitive (uses sort_keys=True)."""
        artifact_a = {"z": 1, "a": 2, "m": 3}
        artifact_b = {"a": 2, "m": 3, "z": 1}

        hash_a = calculate_hash_for_new_artifact(artifact_a)
        hash_b = calculate_hash_for_new_artifact(artifact_b)

        self.assertEqual(hash_a, hash_b)

    def test_new_artifact_hash_is_valid_sha256_hex(self):
        """New artifact hash is a valid 64-character hexadecimal string."""
        artifact = {"test": "data"}
        result = calculate_hash_for_new_artifact(artifact)

        self.assertEqual(len(result), 64)
        self.assertTrue(all(c in '0123456789abcdef' for c in result))


if __name__ == '__main__':
    unittest.main()
