#!/usr/bin/env python3
"""
Test that encryption constants never change.

These tests protect against breaking changes to encryption parameters.
If ANY of these tests fail, it means ALL existing encrypted databases
will become unreadable. REVERT THE CHANGE IMMEDIATELY.

This test file exists because a "documentation only" commit changed
the PBKDF2 salt and broke all existing user databases.
"""

import hashlib
from hashlib import pbkdf2_hmac

import pytest


class TestEncryptionConstants:
    """
    Verify that encryption constants haven't changed.

    CRITICAL: These values are used to derive encryption keys.
    Changing ANY of them will make existing databases unreadable.
    """

    def test_salt_value_is_stable(self):
        """
        Ensure the PBKDF2 salt value hasn't changed.

        WARNING: Changing this salt will break ALL existing user databases!
        If this test fails, you MUST revert the salt change.
        """
        from local_deep_research.database.sqlcipher_utils import (
            PBKDF2_PLACEHOLDER_SALT,
        )

        expected_salt = b"no salt"

        assert PBKDF2_PLACEHOLDER_SALT == expected_salt, (
            f"CRITICAL: PBKDF2 salt has changed!\n"
            f"Expected: {expected_salt!r}\n"
            f"Actual:   {PBKDF2_PLACEHOLDER_SALT!r}\n\n"
            "This will break ALL existing encrypted databases!\n"
            "Users will be unable to log in.\n"
            "REVERT THIS CHANGE IMMEDIATELY."
        )

    def test_kdf_iterations_stable(self):
        """
        Ensure KDF iterations haven't changed.

        Changing this will make existing databases unreadable.
        """
        from local_deep_research.database.sqlcipher_utils import (
            DEFAULT_KDF_ITERATIONS,
        )

        expected_iterations = 256000

        assert DEFAULT_KDF_ITERATIONS == expected_iterations, (
            f"CRITICAL: KDF iterations changed!\n"
            f"Expected: {expected_iterations}\n"
            f"Actual:   {DEFAULT_KDF_ITERATIONS}\n\n"
            "This will break ALL existing encrypted databases!\n"
            "REVERT THIS CHANGE IMMEDIATELY."
        )

    def test_hmac_algorithm_stable(self):
        """
        Ensure HMAC algorithm hasn't changed.

        Changing this will make existing databases unreadable.
        """
        from local_deep_research.database.sqlcipher_utils import (
            DEFAULT_HMAC_ALGORITHM,
        )

        expected_algorithm = "HMAC_SHA512"

        assert DEFAULT_HMAC_ALGORITHM == expected_algorithm, (
            f"CRITICAL: HMAC algorithm changed!\n"
            f"Expected: {expected_algorithm}\n"
            f"Actual:   {DEFAULT_HMAC_ALGORITHM}\n\n"
            "This will break ALL existing encrypted databases!\n"
            "REVERT THIS CHANGE IMMEDIATELY."
        )

    def test_page_size_stable(self):
        """
        Ensure cipher page size hasn't changed.

        Changing this will make existing databases unreadable.
        """
        from local_deep_research.database.sqlcipher_utils import (
            DEFAULT_PAGE_SIZE,
        )

        expected_page_size = 16384  # 16KB

        assert DEFAULT_PAGE_SIZE == expected_page_size, (
            f"CRITICAL: Page size changed!\n"
            f"Expected: {expected_page_size}\n"
            f"Actual:   {DEFAULT_PAGE_SIZE}\n\n"
            "This will break ALL existing encrypted databases!\n"
            "REVERT THIS CHANGE IMMEDIATELY."
        )

    def test_kdf_algorithm_stable(self):
        """
        Ensure KDF algorithm hasn't changed.

        Changing this will make existing databases unreadable.
        """
        from local_deep_research.database.sqlcipher_utils import (
            DEFAULT_KDF_ALGORITHM,
        )

        expected_algorithm = "PBKDF2_HMAC_SHA512"

        assert DEFAULT_KDF_ALGORITHM == expected_algorithm, (
            f"CRITICAL: KDF algorithm changed!\n"
            f"Expected: {expected_algorithm}\n"
            f"Actual:   {DEFAULT_KDF_ALGORITHM}\n\n"
            "This will break ALL existing encrypted databases!\n"
            "REVERT THIS CHANGE IMMEDIATELY."
        )

    def test_key_derivation_produces_expected_output(self):
        """
        Verify the key derivation function produces the expected output.

        This test uses a known password and verifies the derived key matches
        the expected hash. This catches ANY change to the key derivation:
        - Salt changes
        - Iteration count changes
        - Algorithm changes
        - Any other parameter changes

        If this test fails, existing databases WILL NOT be openable.
        """
        from local_deep_research.database.sqlcipher_utils import (
            PBKDF2_PLACEHOLDER_SALT,
            DEFAULT_KDF_ITERATIONS,
        )

        # Use a known test password
        test_password = "test_password_for_key_derivation_check"

        # Derive the key the same way the production code does
        derived_key = pbkdf2_hmac(
            "sha512",
            test_password.encode(),
            PBKDF2_PLACEHOLDER_SALT,
            DEFAULT_KDF_ITERATIONS,
        )

        # This is the expected hash of the derived key
        # Generated with: hashlib.sha256(derived_key).hexdigest()
        # If this changes, ALL existing databases will break!
        # DevSkim: ignore DS173237 - This is a verification hash, not a secret
        expected_key_hash = (
            "cfac783084917231b28210859f7722be29b54120161f43709363c07cfc6c63ed"
        )

        actual_key_hash = hashlib.sha256(derived_key).hexdigest()

        assert actual_key_hash == expected_key_hash, (
            f"CRITICAL: Key derivation output has changed!\n"
            f"Expected hash: {expected_key_hash}\n"
            f"Actual hash:   {actual_key_hash}\n\n"
            "This means the encryption key for the same password is now different.\n"
            "ALL existing user databases will be unreadable!\n"
            "REVERT WHATEVER CHANGE CAUSED THIS IMMEDIATELY."
        )


if __name__ == "__main__":
    pytest.main([__file__, "-v"])
