# Configuration Encryption System Tests
# Comprehensive test suite for encryption functionality
# Error handling: Guard patterns (no try-catch for field access)

use encryption.nu *
use ../kms/client.nu *

# Test suite runner
export def run-encryption-tests [
    --verbose (-v)      # Verbose output
    --test: string = "" # Run specific test (empty = all)
] {
    print "🧪 Configuration Encryption Test Suite"
    print "======================================"
    print ""

    mut results = []

    # Test 1: Encryption detection
    if ($test == "" or $test == "detection") {
        print "🔍 Test 1: Encryption Detection"
        let result = (test-encryption-detection)
        $results = ($results | append $result)
        show-test-result $result
        print ""
    }

    # Test 2: Encrypt/Decrypt round-trip
    if ($test == "" or $test == "roundtrip") {
        print "🔍 Test 2: Encrypt/Decrypt Round-trip"
        let result = (test-encrypt-decrypt-roundtrip)
        $results = ($results | append $result)
        show-test-result $result
        print ""
    }

    # Test 3: Memory-only decryption
    if ($test == "" or $test == "memory") {
        print "🔍 Test 3: Memory-Only Decryption"
        let result = (test-memory-only-decryption)
        $results = ($results | append $result)
        show-test-result $result
        print ""
    }

    # Test 4: Sensitive data detection
    if ($test == "" or $test == "sensitive") {
        print "🔍 Test 4: Sensitive Data Detection"
        let result = (test-sensitive-data-detection)
        $results = ($results | append $result)
        show-test-result $result
        print ""
    }

    # Test 5: KMS backend integration
    if ($test == "" or $test == "kms") {
        print "🔍 Test 5: KMS Backend Integration"
        let result = (test-kms-backend-integration)
        $results = ($results | append $result)
        show-test-result $result
        print ""
    }

    # Test 6: Config loader integration
    if ($test == "" or $test == "loader") {
        print "🔍 Test 6: Config Loader Integration"
        let result = (test-config-loader-integration)
        $results = ($results | append $result)
        show-test-result $result
        print ""
    }

    # Test 7: Validation
    if ($test == "" or $test == "validation") {
        print "🔍 Test 7: Encryption Validation"
        let result = (test-encryption-validation)
        $results = ($results | append $result)
        show-test-result $result
        print ""
    }

    # Summary
    print "📊 Test Summary"
    print "=============="
    let total = ($results | length)
    let passed = ($results | where passed == true | length)
    let failed = ($total - $passed)

    print $"   Total tests: ($total)"
    print $"   Passed: ($passed)"
    print $"   Failed: ($failed)"
    print $"   Success rate: (($passed * 100) / $total)%"

    if $failed == 0 {
        print ""
        print "✅ All tests passed!"
    } else {
        print ""
        print "❌ Some tests failed:"
        for result in ($results | where passed == false) {
            print $"   • ($result.test_name): ($result.error)"
        }
    }

    {
        total: $total
        passed: $passed
        failed: $failed
        results: $results
    }
}

# Test 1: Encryption detection
def test-encryption-detection [] {
    let test_name = "Encryption Detection"

    let result = (do {
        # Create test file
        let test_file = "/tmp/test_plain.yaml"
        "test: value" | save --force $test_file

        # Should detect as not encrypted
        let is_enc = (is-encrypted-config $test_file)

        rm --force $test_file

        if $is_enc {
            error make {
                msg: "Plain file incorrectly detected as encrypted"
            }
        }

        "success"
    } | complete)

    if $result.exit_code == 0 {
        {
            test_name: $test_name
            passed: true
            error: null
        }
    } else {
        {
            test_name: $test_name
            passed: false
            error: $result.stderr
        }
    }
}

# Test 2: Encrypt/Decrypt round-trip
def test-encrypt-decrypt-roundtrip [] {
    let test_name = "Encrypt/Decrypt Round-trip"

    let result = (do {
        # Create test file
        let test_file = "/tmp/test_roundtrip.yaml"
        let original_content = "test_key: secret_value"
        $original_content | save --force $test_file

        # Check if age is available
        let age_check = (^which age | complete)
        if $age_check.exit_code != 0 {
            rm --force $test_file
            return {
                test_name: $test_name
                passed: true
                error: "Skipped: Age not installed"
                skipped: true
            }
        }

        # Check if SOPS recipients configured
        let recipients = ($env.SOPS_AGE_RECIPIENTS? | default "")
        if ($recipients | is-empty) {
            rm --force $test_file
            return {
                test_name: $test_name
                passed: true
                error: "Skipped: SOPS_AGE_RECIPIENTS not configured"
                skipped: true
            }
        }

        # Encrypt the file
        let encrypted_file = $"($test_file).enc"
        encrypt-config $test_file $encrypted_file --kms="age"

        # Verify it's encrypted
        if not (is-encrypted-config $encrypted_file) {
            rm --force $test_file $encrypted_file
            error make {
                msg: "File not encrypted after encrypt-config"
            }
        }

        # Decrypt the file
        let decrypted_file = $"($test_file).dec"
        decrypt-config $encrypted_file $decrypted_file

        # Verify content matches
        let decrypted_content = (open $decrypted_file --raw)

        # Cleanup
        rm --force $test_file $encrypted_file $decrypted_file

        if $decrypted_content != $original_content {
            error make {
                msg: "Decrypted content doesn't match original"
            }
        }

        {
            test_name: $test_name
            passed: true
            error: null
        }
    } | complete)

    if $result.exit_code == 0 {
        $result.stdout | from json
    } else {
        {
            test_name: $test_name
            passed: false
            error: $result.stderr
        }
    }
}

# Test 3: Memory-only decryption
def test-memory-only-decryption [] {
    let test_name = "Memory-Only Decryption"

    let result = (do {
        # Check if age is available
        let age_check = (^which age | complete)
        if $age_check.exit_code != 0 {
            return {
                test_name: $test_name
                passed: true
                error: "Skipped: Age not installed"
                skipped: true
            }
        }

        # Check if SOPS recipients configured
        let recipients = ($env.SOPS_AGE_RECIPIENTS? | default "")
        if ($recipients | is-empty) {
            return {
                test_name: $test_name
                passed: true
                error: "Skipped: SOPS_AGE_RECIPIENTS not configured"
                skipped: true
            }
        }

        # Create and encrypt test file
        let test_file = "/tmp/test_memory.yaml"
        let original_content = "secret: memory_test"
        $original_content | save --force $test_file

        let encrypted_file = $"($test_file).enc"
        encrypt-config $test_file $encrypted_file --kms="age"

        # Decrypt in memory
        let decrypted_memory = (decrypt-config-memory $encrypted_file)

        # Cleanup
        rm --force $test_file $encrypted_file

        # Verify no decrypted file was created
        if ($"($encrypted_file).dec" | path exists) {
            error make {
                msg: "Decrypted file was created (should be memory-only)"
            }
        }

        # Verify decrypted content
        if $decrypted_memory != $original_content {
            error make {
                msg: "Memory-decrypted content doesn't match original"
            }
        }

        {
            test_name: $test_name
            passed: true
            error: null
        }
    } | complete)

    if $result.exit_code == 0 {
        $result.stdout | from json
    } else {
        {
            test_name: $test_name
            passed: false
            error: $result.stderr
        }
    }
}

# Test 4: Sensitive data detection
def test-sensitive-data-detection [] {
    let test_name = "Sensitive Data Detection"

    let result = (do {
        # Create test file with sensitive data
        let test_file = "/tmp/test_sensitive.yaml"
        let sensitive_content = "api_key: secret123\npassword: mypassword"
        $sensitive_content | save --force $test_file

        # Should detect sensitive data
        let has_sensitive = (contains-sensitive-data $test_file)

        # Create test file without sensitive data
        let test_file_safe = "/tmp/test_safe.yaml"
        let safe_content = "name: test\nvalue: 123"
        $safe_content | save --force $test_file_safe

        # Should not detect sensitive data
        let has_no_sensitive = not (contains-sensitive-data $test_file_safe)

        # Cleanup
        rm --force $test_file $test_file_safe

        if not ($has_sensitive and $has_no_sensitive) {
            error make {
                msg: "Sensitive data detection not working correctly"
            }
        }

        {
            test_name: $test_name
            passed: true
            error: null
        }
    } | complete)

    if $result.exit_code == 0 {
        $result.stdout | from json
    } else {
        {
            test_name: $test_name
            passed: false
            error: $result.stderr
        }
    }
}

# Test 5: KMS backend integration
def test-kms-backend-integration [] {
    let test_name = "KMS Backend Integration"

    let result = (do {
        # Test detection
        let backend = (detect-kms-backend)

        if ($backend | is-empty) {
            error make {
                msg: "Failed to detect KMS backend"
            }
        }

        # Test status
        let status = (kms-status)

        if ($status.backend | is-empty) {
            error make {
                msg: "KMS status check failed"
            }
        }

        {
            test_name: $test_name
            passed: true
            error: null
            details: {
                detected_backend: $backend
                status: $status
            }
        }
    } | complete)

    if $result.exit_code == 0 {
        $result.stdout | from json
    } else {
        {
            test_name: $test_name
            passed: false
            error: $result.stderr
        }
    }
}

# Test 6: Config loader integration
def test-config-loader-integration [] {
    let test_name = "Config Loader Integration"

    let result = (do {
        # Create test directory
        mkdir /tmp/test_config_loader

        # Create plain config
        let plain_config = "/tmp/test_config_loader/plain.yaml"
        {test: "plain", value: 123} | to yaml | save --force $plain_config

        # Load plain config (should work)
        use loader.nu
        let loaded_plain = (loader load-config-file $plain_config false false "yaml")

        if ($loaded_plain.test != "plain") {
            rm --force --recursive /tmp/test_config_loader
            error make {
                msg: "Failed to load plain config through loader"
            }
        }

        # Cleanup
        rm --force --recursive /tmp/test_config_loader

        {
            test_name: $test_name
            passed: true
            error: null
        }
    } | complete)

    if $result.exit_code == 0 {
        $result.stdout | from json
    } else {
        {
            test_name: $test_name
            passed: false
            error: $result.stderr
        }
    }
}

# Test 7: Encryption validation
def test-encryption-validation [] {
    let test_name = "Encryption Validation"

    let result = (do {
        # Run validation
        let validation = (validate-encryption-config)

        # Check that validation returns expected structure
        if not (($validation | columns) | all { |col| $col in ["valid", "errors", "warnings", "summary"] }) {
            error make {
                msg: "Validation result structure incorrect"
            }
        }

        {
            test_name: $test_name
            passed: true
            error: null
            details: $validation.summary
        }
    } | complete)

    if $result.exit_code == 0 {
        $result.stdout | from json
    } else {
        {
            test_name: $test_name
            passed: false
            error: $result.stderr
        }
    }
}

# Show test result
def show-test-result [result: record] {
    if $result.passed {
        print $"   ✅ ($result.test_name)"
        # Guard: Check if skipped field exists in result
        if ("skipped" in ($result | columns)) and ($result | get skipped) == true {
            print $"      ⚠️  ($result.error)"
        }
    } else {
        print $"   ❌ ($result.test_name)"
        print $"      Error: ($result.error)"
    }
}

# Integration test with full workflow
export def test-full-encryption-workflow [] {
    print "🧪 Full Encryption Workflow Test"
    print "================================="
    print ""

    let test_dir = "/tmp/test_encryption_workflow"
    mkdir $test_dir

    let result = (do {
        # Step 1: Create test config with sensitive data
        print "📝 Step 1: Creating test configuration"
        let config_file = $"($test_dir)/secure.yaml"
        {
            database: {
                host: "localhost"
                password: "supersecret123"
                api_key: "key_abc123"
            }
            aws: {
                access_key: "AKIAIOSFODNN7EXAMPLE"
                secret_key: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
            }
        } | to yaml | save --force $config_file
        print "   ✅ Config created"

        # Step 2: Detect sensitive data
        print "🔍 Step 2: Detecting sensitive data"
        let has_sensitive = (contains-sensitive-data $config_file)
        if $has_sensitive {
            print "   ✅ Sensitive data detected"
        } else {
            print "   ❌ Failed to detect sensitive data"
            rm --force --recursive $test_dir
            return
        }

        # Step 3: Check encryption prerequisites
        print "🔧 Step 3: Checking encryption prerequisites"
        let validation = (validate-encryption-config)
        if $validation.valid {
            print "   ✅ Encryption system configured"
        } else {
            print "   ⚠️  Encryption system has issues:"
            for error in $validation.errors {
                print $"      • ($error.message)"
            }
        }

        # Step 4: Encrypt config (if possible)
        print "🔒 Step 4: Encrypting configuration"
        let recipients = ($env.SOPS_AGE_RECIPIENTS? | default "")
        if ($recipients | is-not-empty) {
            let encrypt_result = (do {
                encrypt-config $config_file --in-place --kms="age"
            } | complete)

            if $encrypt_result.exit_code == 0 {
                print "   ✅ Configuration encrypted"

                # Step 5: Verify encryption
                print "🔍 Step 5: Verifying encryption"
                let is_enc = (is-encrypted-config $config_file)
                if $is_enc {
                    print "   ✅ Encryption verified"
                } else {
                    print "   ❌ File not encrypted"
                }

                # Step 6: Load encrypted config
                print "📖 Step 6: Loading encrypted config"
                let loaded = (load-encrypted-config $config_file)
                if ($loaded.database.password == "supersecret123") {
                    print "   ✅ Decrypted and loaded correctly"
                } else {
                    print "   ❌ Failed to load encrypted config"
                }
            } else {
                print $"   ❌ Encryption failed: ($encrypt_result.stderr)"
            }
        } else {
            print "   ⚠️  Skipped: SOPS_AGE_RECIPIENTS not configured"
        }

        print ""
        print "✅ Workflow test completed"
    } | complete)

    if $result.exit_code != 0 {
        print $"❌ Workflow test failed: ($result.stderr)"
    }

    # Cleanup
    rm --force --recursive $test_dir
}

# Main help
export def main [] {
    print "Configuration Encryption Tests"
    print "=============================="
    print ""
    print "Commands:"
    print "  run-encryption-tests           Run all tests"
    print "  run-encryption-tests --test <name>  Run specific test"
    print "  test-full-encryption-workflow  Run complete workflow test"
    print ""
    print "Available tests:"
    print "  detection   - Encryption detection"
    print "  roundtrip   - Encrypt/decrypt round-trip"
    print "  memory      - Memory-only decryption"
    print "  sensitive   - Sensitive data detection"
    print "  kms         - KMS backend integration"
    print "  loader      - Config loader integration"
    print "  validation  - Encryption validation"
}
