# Module: Configuration Validators
# Purpose: Provides validation functions for configuration integrity, types, and semantic correctness.
# Dependencies: None (core utility)

# Configuration Validation and Detection Engine
# Validates configuration structures and detects potential security/dependency issues

use std log

# Validate interpolation patterns and detect potential issues
export def validate-interpolation [
    config: record
    --detailed = false              # Show detailed validation results
] {
    mut errors = []
    mut warnings = []

    # Convert config to JSON for pattern detection
    let json_str = ($config | to json)

    # Check for unresolved interpolation patterns
    let unresolved_patterns = (detect-unresolved-patterns $json_str)
    if ($unresolved_patterns | length) > 0 {
        $errors = ($errors | append {
            type: "unresolved_interpolation"
            severity: "error"
            patterns: $unresolved_patterns
            message: $"Unresolved interpolation patterns found: ($unresolved_patterns | str join ', ')"
        })
    }

    # Check for circular dependencies
    let circular_deps = (detect-circular-dependencies $json_str)
    if ($circular_deps | length) > 0 {
        $errors = ($errors | append {
            type: "circular_dependency"
            severity: "error"
            dependencies: $circular_deps
            message: $"Circular interpolation dependencies detected: ($circular_deps | str join ', ')"
        })
    }

    # Check for unsafe environment variable access
    let unsafe_env_vars = (detect-unsafe-env-patterns $json_str)
    if ($unsafe_env_vars | length) > 0 {
        $warnings = ($warnings | append {
            type: "unsafe_env_access"
            severity: "warning"
            variables: $unsafe_env_vars
            message: $"Potentially unsafe environment variable access: ($unsafe_env_vars | str join ', ')"
        })
    }

    # Validate git repository context
    let git_validation = (validate-git-context $json_str)
    if not $git_validation.valid {
        $warnings = ($warnings | append {
            type: "git_context"
            severity: "warning"
            message: $git_validation.message
        })
    }

    let has_errors = ($errors | length) > 0
    let has_warnings = ($warnings | length) > 0

    if not $detailed and $has_errors {
        let error_messages = ($errors | each { |err| $err.message })
        error make {
            msg: ($error_messages | str join "; ")
        }
    }

    {
        valid: (not $has_errors),
        errors: $errors,
        warnings: $warnings,
        summary: {
            total_errors: ($errors | length),
            total_warnings: ($warnings | length),
            interpolation_patterns_detected: (count-interpolation-patterns $json_str)
        }
    }
}

# Security-hardened interpolation with input validation
export def secure-interpolation [
    config: record
    --allow-unsafe = false          # Allow potentially unsafe patterns
    --max-depth = 5                 # Maximum interpolation depth
] {
    # Security checks before interpolation
    let security_validation = (validate-interpolation-security $config $allow_unsafe)

    if not $security_validation.valid {
        error make {
            msg: $"Security validation failed: ($security_validation.errors | str join '; ')"
        }
    }

    # Apply interpolation with depth limiting
    let base_path = ($config | get -o paths.base | default "")
    if ($base_path | is-not-empty) {
        interpolate-with-depth-limit $config $base_path $max_depth
    } else {
        $config
    }
}

# Detect unresolved interpolation patterns
export def detect-unresolved-patterns [
    text: string
] {
    # Find patterns that look like interpolation but might not be handled
    let unknown_patterns = ($text | str replace --regex "\\{\\{([^}]+)\\}\\}" "")

    # Known patterns that should be resolved
    let known_patterns = [
        "paths.base" "env\\." "now\\." "git\\." "sops\\." "providers\\." "path\\.join"
    ]

    mut unresolved = []

    # Check for patterns that don't match known types
    let all_matches = ($text | str replace --regex "\\{\\{([^}]+)\\}\\}" "$1")
    if ($all_matches | str contains "{{") {
        # Basic detection - in a real implementation, this would be more sophisticated
        let potential_unknown = ($text | str replace --regex "\\{\\{(\\w+\\.\\w+)\\}\\}" "")
        if ($text | str contains "{{unknown.") {
            $unresolved = ($unresolved | append "unknown.*")
        }
    }

    $unresolved
}

# Detect circular interpolation dependencies
export def detect-circular-dependencies [
    text: string
] {
    mut circular_deps = []

    # Simple detection for self-referencing patterns
    if (($text | str contains "{{paths.base}}") and ($text | str contains "paths.base.*{{paths.base}}")) {
        $circular_deps = ($circular_deps | append "paths.base -> paths.base")
    }

    $circular_deps
}

# Detect unsafe environment variable patterns
export def detect-unsafe-env-patterns [
    text: string
] {
    mut unsafe_vars = []

    # Patterns that might be dangerous
    let dangerous_patterns = ["PATH" "LD_LIBRARY_PATH" "PYTHONPATH" "SHELL" "PS1"]

    for pattern in $dangerous_patterns {
        if ($text | str contains $"{{env.($pattern)}}") {
            $unsafe_vars = ($unsafe_vars | append $pattern)
        }
    }

    $unsafe_vars
}

# Validate git repository context for git interpolations
export def validate-git-context [
    text: string
] {
    if ($text | str contains "{{git.") {
        # Check if we're in a git repository
        let git_check = (do { ^git rev-parse --git-dir err> (if $nu.os-info.name == "windows" { "NUL" } else { "/dev/null" }) } | complete)
        let is_git_repo = ($git_check.exit_code == 0)

        if not $is_git_repo {
            return {
                valid: false
                message: "Git interpolation patterns detected but not in a git repository"
            }
        }
    }

    { valid: true, message: "" }
}

# Count interpolation patterns for metrics
export def count-interpolation-patterns [
    text: string
] {
    # Count all {{...}} patterns by finding matches
    # Simple approximation: count occurrences of "{{"
    let pattern_count = ($text | str replace --all "{{" "\n{{" | lines | where ($it | str contains "{{") | length)
    $pattern_count
}

# Validate interpolation security
def validate-interpolation-security [
    config: record
    allow_unsafe: bool
] {
    mut errors = []
    let json_str = ($config | to json)

    # Check for code injection patterns
    let dangerous_patterns = [
        "\\$\\(" "\\`" "\\;" "\\|\\|" "\\&&" "rm " "sudo " "eval " "exec "
    ]

    for pattern in $dangerous_patterns {
        if ($json_str =~ $pattern) {
            $errors = ($errors | append $"Potential code injection pattern detected: ($pattern)")
        }
    }

    # Check for unsafe environment variable access
    if not $allow_unsafe {
        let unsafe_env_vars = ["PATH" "LD_LIBRARY_PATH" "PYTHONPATH" "PS1" "PROMPT_COMMAND"]
        for var in $unsafe_env_vars {
            if ($json_str | str contains $"{{env.($var)}}") {
                $errors = ($errors | append $"Unsafe environment variable access: ($var)")
            }
        }
    }

    # Check for path traversal attempts
    if (($json_str | str contains "../") or ($json_str | str contains "..\\")) {
        $errors = ($errors | append "Path traversal attempt detected")
    }

    {
        valid: (($errors | length) == 0)
        errors: $errors
    }
}
