# Remote Execution Library for Nushell Infrastructure
# Secure, audited remote script execution capabilities

# Execute a Nushell script remotely with security restrictions
export def nu-remote-exec [
    script_path: string   # Path to the Nushell script to execute
    --readonly(-r)        # Force read-only mode
    --timeout(-t): int = 300  # Execution timeout in seconds
    --audit(-a)           # Enable audit logging
] -> record {
    # Validate script path
    if not ($script_path | path exists) {
        return {
            success: false
            error: $"Script not found: ($script_path)"
            output: ""
            duration: 0
        }
    }

    # Security checks
    let allowed_paths = ($env.NUSHELL_ALLOWED_PATHS? | default "/tmp,/var/log,/proc,/sys" | split row ",")
    let script_dir = ($script_path | path dirname)

    if not ($allowed_paths | any {|path| $script_dir | str starts-with $path}) {
        return {
            success: false
            error: $"Script path not in allowed directories: ($script_dir)"
            output: ""
            duration: 0
        }
    }

    # Prepare execution environment
    let start_time = (date now)
    let session_id = (random uuid)

    # Audit logging if enabled
    if ($audit or ($env.NUSHELL_AUDIT_ENABLED? | default false)) {
        let audit_entry = {
            timestamp: ($start_time | format date "%Y-%m-%d %H:%M:%S")
            session_id: $session_id
            action: "remote-exec"
            script: $script_path
            readonly: $readonly
            user: ($env.USER? | default "unknown")
            hostname: ($env.HOSTNAME? | default "unknown")
        }
        $audit_entry | to json | save -a ($env.NUSHELL_AUDIT_FILE? | default "/tmp/nushell-audit.log")
    }

    # Build execution command with security flags
    mut nu_args = ["--no-config-file"]

    if $readonly or ($env.NUSHELL_READONLY_MODE? | default true) {
        $nu_args = ($nu_args | append "--no-history")
    }

    # Set resource limits
    let memory_limit = ($env.NUSHELL_MAX_MEMORY? | default "256MB")
    let cpu_time = ($env.NUSHELL_MAX_CPU_TIME? | default "30s")

    try {
        # Execute with timeout and resource limits
        let result = (timeout $"($timeout)s" nu ...$nu_args $script_path | complete)
        let end_time = (date now)
        let duration = (($end_time - $start_time) / 1ms | math round)

        # Log completion
        if ($audit or ($env.NUSHELL_AUDIT_ENABLED? | default false)) {
            let completion_entry = {
                timestamp: ($end_time | format date "%Y-%m-%d %H:%M:%S")
                session_id: $session_id
                action: "remote-exec-complete"
                exit_code: $result.exit_code
                duration_ms: $duration
                output_lines: ($result.stdout | lines | length)
            }
            $completion_entry | to json | save -a ($env.NUSHELL_AUDIT_FILE? | default "/tmp/nushell-audit.log")
        }

        return {
            success: ($result.exit_code == 0)
            error: $result.stderr
            output: $result.stdout
            duration: $duration
            exit_code: $result.exit_code
            session_id: $session_id
        }

    } catch { |err|
        let end_time = (date now)
        let duration = (($end_time - $start_time) / 1ms | math round)

        # Log error
        if ($audit or ($env.NUSHELL_AUDIT_ENABLED? | default false)) {
            let error_entry = {
                timestamp: ($end_time | format date "%Y-%m-%d %H:%M:%S")
                session_id: $session_id
                action: "remote-exec-error"
                error: ($err | get msg)
                duration_ms: $duration
            }
            $error_entry | to json | save -a ($env.NUSHELL_AUDIT_FILE? | default "/tmp/nushell-audit.log")
        }

        return {
            success: false
            error: ($err | get msg)
            output: ""
            duration: $duration
            exit_code: 1
            session_id: $session_id
        }
    }
}

# Execute a command pipeline remotely with streaming output
export def nu-remote-stream [
    command: string       # Command to execute
    --filter(-f): string  # Optional filter expression
    --format: string = "table"  # Output format (table, json, yaml)
    --lines(-l): int      # Limit output lines
] -> any {
    # Security validation
    let blocked_commands = ($env.NUSHELL_BLOCKED_COMMANDS? | default "" | split row ",")
    let cmd_parts = ($command | split row " ")
    let cmd_name = ($cmd_parts | first)

    if $cmd_name in $blocked_commands {
        error make {msg: $"Command '($cmd_name)' is blocked for security reasons"}
    }

    # Build pipeline
    mut pipeline = $command

    if ($filter | is-not-empty) {
        $pipeline = $"($pipeline) | ($filter)"
    }

    if ($lines | is-not-empty) {
        $pipeline = $"($pipeline) | first ($lines)"
    }

    # Format output
    match $format {
        "json" => { $pipeline = $"($pipeline) | to json" }
        "yaml" => { $pipeline = $"($pipeline) | to yaml" }
        "csv" => { $pipeline = $"($pipeline) | to csv" }
        _ => { $pipeline = $"($pipeline) | table" }
    }

    # Execute with audit
    if ($env.NUSHELL_AUDIT_ENABLED? | default false) {
        let audit_entry = {
            timestamp: (date now | format date "%Y-%m-%d %H:%M:%S")
            action: "remote-stream"
            command: $command
            filter: ($filter | default "")
            format: $format
        }
        $audit_entry | to json | save -a ($env.NUSHELL_AUDIT_FILE? | default "/tmp/nushell-audit.log")
    }

    # Execute the pipeline
    nu -c $pipeline
}

# Validate script security before execution
export def nu-validate-script [
    script_path: string
] -> record {
    if not ($script_path | path exists) {
        return {valid: false, reason: "Script file not found"}
    }

    let content = (open $script_path)
    let blocked_patterns = [
        "rm -rf"
        "sudo"
        "su -"
        "chmod 777"
        "wget http://"
        "curl http://"
        "nc -"
        "telnet"
        "/dev/tcp"
        "eval"
        "exec"
    ]

    for pattern in $blocked_patterns {
        if ($content | str contains $pattern) {
            return {
                valid: false
                reason: $"Script contains blocked pattern: ($pattern)"
            }
        }
    }

    # Check for allowed paths only
    let allowed_paths = ($env.NUSHELL_ALLOWED_PATHS? | default "/tmp,/var/log,/proc,/sys" | split row ",")
    let path_accesses = ($content | find -r "/(etc|root|home|usr/bin)" | length)

    if $path_accesses > 0 {
        return {
            valid: false
            reason: "Script accesses restricted system paths"
        }
    }

    return {valid: true, reason: "Script validation passed"}
}

# Health check for remote Nushell environment
export def nu-health-check [] -> record {
    let start_time = (date now)

    mut health = {
        status: "healthy"
        checks: {}
        timestamp: ($start_time | format date "%Y-%m-%d %H:%M:%S")
    }

    # Check Nushell version
    try {
        let version = (version | get version)
        $health.checks = ($health.checks | insert nushell_version {status: "ok", value: $version})
    } catch {
        $health.checks = ($health.checks | insert nushell_version {status: "error", value: "unknown"})
        $health.status = "degraded"
    }

    # Check environment variables
    let required_vars = ["NUSHELL_HOME", "NUSHELL_EXECUTION_MODE"]
    for var in $required_vars {
        if ($env | get -i $var | is-empty) {
            $health.checks = ($health.checks | insert $"env_($var)" {status: "error", value: "missing"})
            $health.status = "unhealthy"
        } else {
            $health.checks = ($health.checks | insert $"env_($var)" {status: "ok", value: ($env | get $var)})
        }
    }

    # Check disk space
    try {
        let disk_usage = (df -h | where Filesystem =~ "/" | first | get "Use%")
        $health.checks = ($health.checks | insert disk_usage {status: "ok", value: $disk_usage})
    } catch {
        $health.checks = ($health.checks | insert disk_usage {status: "error", value: "unknown"})
    }

    # Check memory usage
    try {
        let mem_info = (free -m | lines | get 1 | split row " " | where $it != "" | get 2)
        $health.checks = ($health.checks | insert memory_mb {status: "ok", value: $mem_info})
    } catch {
        $health.checks = ($health.checks | insert memory_mb {status: "error", value: "unknown"})
    }

    return $health
}