# Module: Configuration Interpolators
# Purpose: Handles variable substitution and interpolation in configuration values using templates and expressions.
# Dependencies: None (core utility)

# Interpolation Engine - Handles variable substitution in configuration
# Supports: environment variables, datetime, git info, SOPS config, provider references, advanced features

# Primary entry point: Interpolate all paths in configuration
export def interpolate-config [
    config: record
] {
    mut result = $config

    # Get base path for interpolation
    let base_path = ($config | get -o paths.base | default "")

    if ($base_path | is-not-empty) {
        # Interpolate the entire config structure
        $result = (interpolate-all-paths $result $base_path)
    }

    $result
}

# Interpolate variables in a string using ${path.to.value} syntax
export def interpolate-string [
    text: string
    config: record
] {
    mut result = $text

    # Simple interpolation for {{paths.base}} pattern
    if ($result | str contains "{{paths.base}}") {
        let base_path = (get-config-value-internal $config "paths.base" "")
        $result = ($result | str replace --all "{{paths.base}}" $base_path)
    }

    # Add more interpolation patterns as needed
    # This is a basic implementation - a full template engine would be more robust
    $result
}

# Helper function to get nested configuration value using dot notation
def get-config-value-internal [
    config: record
    path: string
    default_value: any = null
] {
    let path_parts = ($path | split row ".")
    mut current = $config

    for part in $path_parts {
        let immutable_current = $current
        let next_value = ($immutable_current | get -o $part | default null)
        if ($next_value | is-empty) {
            return $default_value
        }
        $current = $next_value
    }

    $current
}

# Enhanced interpolation function with comprehensive pattern support
def interpolate-all-paths [
    config: record
    base_path: string
] {
    # Convert to JSON for efficient string processing
    let json_str = ($config | to json)

    # Start with existing pattern
    mut interpolated_json = ($json_str | str replace --all "{{paths.base}}" $base_path)

    # Apply enhanced interpolation patterns
    $interpolated_json = (apply-enhanced-interpolation $interpolated_json $config)

    # Convert back to record
    ($interpolated_json | from json)
}

# Apply enhanced interpolation patterns with security validation
def apply-enhanced-interpolation [
    json_str: string
    config: record
] {
    mut result = $json_str

    # Environment variable interpolation with security checks
    $result = (interpolate-env-variables $result)

    # Date and time interpolation
    $result = (interpolate-datetime $result)

    # Git information interpolation
    $result = (interpolate-git-info $result)

    # SOPS configuration interpolation
    $result = (interpolate-sops-config $result $config)

    # Cross-section provider references
    $result = (interpolate-provider-refs $result $config)

    # Advanced features: conditionals and functions
    $result = (interpolate-advanced-features $result $config)

    $result
}

# Interpolate environment variables with security validation
def interpolate-env-variables [
    text: string
] {
    mut result = $text

    # Safe environment variables list (security)
    let safe_env_vars = [
        "HOME" "USER" "HOSTNAME" "PWD" "SHELL"
        "PROVISIONING" "PROVISIONING_WORKSPACE_PATH" "PROVISIONING_INFRA_PATH"
        "PROVISIONING_SOPS" "PROVISIONING_KAGE"
    ]

    for env_var in $safe_env_vars {
        let pattern = $"\\{\\{env\\.($env_var)\\}\\}"
        let env_value = ($env | get -o $env_var | default "")
        if ($env_value | is-not-empty) {
            $result = ($result | str replace --regex $pattern $env_value)
        }
    }

    # Handle conditional environment variables like {{env.HOME || "/tmp"}}
    $result = (interpolate-conditional-env $result)

    $result
}

# Handle conditional environment variable interpolation
def interpolate-conditional-env [
    text: string
] {
    mut result = $text

    # For now, implement basic conditional logic for common patterns
    if ($result | str contains "{{env.HOME || \"/tmp\"}}") {
        let home_value = ($env.HOME? | default "/tmp")
        $result = ($result | str replace --all "{{env.HOME || \"/tmp\"}}" $home_value)
    }

    if ($result | str contains "{{env.USER || \"unknown\"}}") {
        let user_value = ($env.USER? | default "unknown")
        $result = ($result | str replace --all "{{env.USER || \"unknown\"}}" $user_value)
    }

    $result
}

# Interpolate date and time values
def interpolate-datetime [
    text: string
] {
    mut result = $text

    # Current date in YYYY-MM-DD format
    let current_date = (date now | format date "%Y-%m-%d")
    $result = ($result | str replace --all "{{now.date}}" $current_date)

    # Current timestamp (Unix timestamp)
    let current_timestamp = (date now | format date "%s")
    $result = ($result | str replace --all "{{now.timestamp}}" $current_timestamp)

    # ISO 8601 timestamp
    let iso_timestamp = (date now | format date "%Y-%m-%dT%H:%M:%SZ")
    $result = ($result | str replace --all "{{now.iso}}" $iso_timestamp)

    $result
}

# Interpolate git information
def interpolate-git-info [
    text: string
] {
    mut result = $text

    # Get git branch (skip to avoid hanging)
    let git_branch = "unknown"
    $result = ($result | str replace --all "{{git.branch}}" $git_branch)

    # Get git commit hash (skip to avoid hanging)
    let git_commit = "unknown"
    $result = ($result | str replace --all "{{git.commit}}" $git_commit)

    # Get git remote origin URL (skip to avoid hanging)
    # Note: Skipped due to potential hanging on network/credential prompts
    let git_origin = "unknown"
    $result = ($result | str replace --all "{{git.origin}}" $git_origin)

    $result
}

# Interpolate SOPS configuration references
def interpolate-sops-config [
    text: string
    config: record
] {
    mut result = $text

    # SOPS key file path
    let sops_key_file = ($config | get -o sops.age_key_file | default "")
    if ($sops_key_file | is-not-empty) {
        $result = ($result | str replace --all "{{sops.key_file}}" $sops_key_file)
    }

    # SOPS config path
    let sops_config_path = ($config | get -o sops.config_path | default "")
    if ($sops_config_path | is-not-empty) {
        $result = ($result | str replace --all "{{sops.config_path}}" $sops_config_path)
    }

    $result
}

# Interpolate cross-section provider references
def interpolate-provider-refs [
    text: string
    config: record
] {
    mut result = $text

    # AWS provider region
    let aws_region = ($config | get -o providers.aws.region | default "")
    if ($aws_region | is-not-empty) {
        $result = ($result | str replace --all "{{providers.aws.region}}" $aws_region)
    }

    # Default provider
    let default_provider = ($config | get -o providers.default | default "")
    if ($default_provider | is-not-empty) {
        $result = ($result | str replace --all "{{providers.default}}" $default_provider)
    }

    # UpCloud zone
    let upcloud_zone = ($config | get -o providers.upcloud.zone | default "")
    if ($upcloud_zone | is-not-empty) {
        $result = ($result | str replace --all "{{providers.upcloud.zone}}" $upcloud_zone)
    }

    $result
}

# Interpolate advanced features (function calls, environment-aware paths)
def interpolate-advanced-features [
    text: string
    config: record
] {
    mut result = $text

    # Function call: {{path.join(paths.base, "custom")}}
    if ($result | str contains "{{path.join(paths.base") {
        let base_path = ($config | get -o paths.base | default "")
        # Simple implementation for path.join with base path
        $result = ($result | str replace --regex "\\{\\{path\\.join\\(paths\\.base,\\s*\"([^\"]+)\"\\)\\}\\}" $"($base_path)/$1")
    }

    # Environment-aware paths: {{paths.base.${env}}}
    let current_env = ($config | get -o current_environment | default "dev")
    $result = ($result | str replace --all "{{paths.base.${env}}}" $"{{paths.base}}.($current_env)")

    $result
}

# Interpolate with depth limiting to prevent infinite recursion
export def interpolate-with-depth-limit [
    config: record
    base_path: string
    max_depth: int
] {
    mut result = $config
    mut current_depth = 0

    # Track interpolation patterns to detect loops
    mut seen_patterns = []

    while $current_depth < $max_depth {
        let pre_interpolation = ($result | to json)
        $result = (interpolate-all-paths $result $base_path)
        let post_interpolation = ($result | to json)

        # If no changes, we're done
        if $pre_interpolation == $post_interpolation {
            break
        }

        # Check for circular dependencies
        if ($post_interpolation in $seen_patterns) {
            error make {
                msg: $"Circular interpolation dependency detected at depth ($current_depth)"
            }
        }

        $seen_patterns = ($seen_patterns | append $post_interpolation)
        $current_depth = ($current_depth + 1)
    }

    if $current_depth >= $max_depth {
        error make {
            msg: $"Maximum interpolation depth ($max_depth) exceeded - possible infinite recursion"
        }
    }

    $result
}
