#!/bin/bash
# Nushell Infrastructure Runtime Installation Script
# Secure installation with version management and safety checks

set -euo pipefail

# Configuration
NUSHELL_VERSION="${NUSHELL_VERSION:-0.107.1}"
INSTALL_DIR="${INSTALL_DIR:-/usr/local/bin}"
CONFIG_DIR="${CONFIG_DIR:-/etc/nushell}"
USER_HOME="${USER_HOME:-$HOME}"
ADMIN_USER="${ADMIN_USER:-$(whoami)}"

# Security settings
NUSHELL_READONLY="${NUSHELL_READONLY:-true}"
NUSHELL_PLUGINS="${NUSHELL_PLUGINS:-false}"
NUSHELL_NETWORK="${NUSHELL_NETWORK:-false}"

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

log() {
    echo -e "${BLUE}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1"
}

error() {
    echo -e "${RED}[ERROR]${NC} $1" >&2
}

warn() {
    echo -e "${YELLOW}[WARN]${NC} $1"
}

success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

# Check prerequisites
check_prerequisites() {
    log "Checking prerequisites..."

    # Check if running as root or with sudo privileges
    if [[ $EUID -eq 0 ]]; then
        warn "Running as root. Consider using a dedicated user for Nushell operations."
    fi

    # Check system architecture
    local arch=$(uname -m)
    case $arch in
        x86_64|amd64)
            NUSHELL_ARCH="x86_64"
            ;;
        aarch64|arm64)
            NUSHELL_ARCH="aarch64"
            ;;
        *)
            error "Unsupported architecture: $arch"
            exit 1
            ;;
    esac

    # Check OS
    local os=$(uname -s)
    case $os in
        Linux)
            NUSHELL_OS="unknown-linux-gnu"
            ;;
        Darwin)
            NUSHELL_OS="apple-darwin"
            ;;
        *)
            error "Unsupported operating system: $os"
            exit 1
            ;;
    esac

    # Check available disk space (minimum 100MB)
    local available_space=$(df "$INSTALL_DIR" | awk 'NR==2 {print $4}')
    if [[ $available_space -lt 102400 ]]; then
        error "Insufficient disk space. Need at least 100MB in $INSTALL_DIR"
        exit 1
    fi

    success "Prerequisites check completed"
}

# Download and verify Nushell
download_nushell() {
    log "Downloading Nushell v${NUSHELL_VERSION} for ${NUSHELL_ARCH}-${NUSHELL_OS}..."

    local download_url="https://github.com/nushell/nushell/releases/download/${NUSHELL_VERSION}/nu-${NUSHELL_VERSION}-${NUSHELL_ARCH}-${NUSHELL_OS}.tar.gz"
    local temp_dir=$(mktemp -d)
    local archive_file="${temp_dir}/nushell.tar.gz"

    # Download with retry logic
    local max_retries=3
    local retry_count=0

    while [[ $retry_count -lt $max_retries ]]; do
        if curl -L --fail --silent --show-error "$download_url" -o "$archive_file"; then
            break
        else
            retry_count=$((retry_count + 1))
            warn "Download attempt $retry_count failed. Retrying..."
            sleep 2
        fi
    done

    if [[ $retry_count -eq $max_retries ]]; then
        error "Failed to download Nushell after $max_retries attempts"
        rm -rf "$temp_dir"
        exit 1
    fi

    # Verify download
    if [[ ! -f "$archive_file" ]] || [[ ! -s "$archive_file" ]]; then
        error "Downloaded file is empty or missing"
        rm -rf "$temp_dir"
        exit 1
    fi

    log "Extracting Nushell..."
    tar -xzf "$archive_file" -C "$temp_dir"

    # Find the nu binary
    local nu_binary=$(find "$temp_dir" -name "nu" -type f -executable | head -1)
    if [[ -z "$nu_binary" ]]; then
        error "Could not find nu binary in downloaded archive"
        rm -rf "$temp_dir"
        exit 1
    fi

    # Install binary
    sudo mkdir -p "$INSTALL_DIR"
    sudo cp "$nu_binary" "$INSTALL_DIR/nu"
    sudo chmod +x "$INSTALL_DIR/nu"

    # Copy additional tools if they exist
    for tool in nu_plugin_kcl nu_plugin_tera nu_plugin_polars; do
        local tool_binary=$(find "$temp_dir" -name "$tool" -type f -executable | head -1)
        if [[ -n "$tool_binary" ]] && [[ "$NUSHELL_PLUGINS" == "true" ]]; then
            sudo cp "$tool_binary" "$INSTALL_DIR/$tool"
            sudo chmod +x "$INSTALL_DIR/$tool"
            log "Installed plugin: $tool"
        fi
    done

    # Cleanup
    rm -rf "$temp_dir"

    success "Nushell installation completed"
}

# Create secure configuration
create_configuration() {
    log "Creating secure Nushell configuration..."

    # Create system-wide config directory
    sudo mkdir -p "$CONFIG_DIR"
    sudo mkdir -p "$CONFIG_DIR/scripts"
    sudo mkdir -p "$CONFIG_DIR/observability"

    # Create user-specific directories
    mkdir -p "$USER_HOME/.config/nushell"
    mkdir -p "$USER_HOME/.local/share/nushell"
    mkdir -p "$USER_HOME/nushell/scripts"
    mkdir -p "$USER_HOME/nushell/observability"
    mkdir -p "$USER_HOME/nushell/lib"

    # Set secure permissions
    chmod 750 "$USER_HOME/nushell"
    chmod 700 "$USER_HOME/nushell/scripts"

    # Create basic configuration files
    cat > "$USER_HOME/.config/nushell/env.nu" << 'EOF'
# Nushell Infrastructure Environment
# Security-focused configuration for infrastructure servers

$env.NUSHELL_HOME = $"($env.HOME)/nushell"
$env.NUSHELL_CONFIG_DIR = $"($env.HOME)/.config/nushell"
$env.NUSHELL_EXECUTION_MODE = "restricted"
$env.NUSHELL_READONLY_MODE = true
$env.NUSHELL_AUDIT_ENABLED = true
$env.NUSHELL_AUDIT_FILE = $"($env.HOME)/nushell/audit.log"

# Security: Sanitize PATH
$env.PATH = ($env.PATH | split row (char esep) | where $it =~ "^/(usr/)?(local/)?bin$|^/(usr/)?sbin$" | str join (char esep))

# Session information
$env.NUSHELL_SESSION_ID = (random uuid)
$env.NUSHELL_SESSION_START = (date now | format date "%Y-%m-%d %H:%M:%S")

print "🔧 Nushell Infrastructure Runtime initialized"
print $"🛡️  Security mode: ($env.NUSHELL_EXECUTION_MODE) | Readonly: ($env.NUSHELL_READONLY_MODE)"
EOF

    cat > "$USER_HOME/.config/nushell/config.nu" << 'EOF'
# Secure Nushell Configuration for Infrastructure Servers

$env.config = {
    show_banner: false
    use_ansi_coloring: true
    edit_mode: emacs
    shell_integration: false
    cd_with_abbreviations: false
    filesize_metric: true
    table_mode: rounded

    history: {
        max_size: 1000
        sync_on_enter: true
        file_format: "plaintext"
        isolation: true
    }

    completions: {
        case_sensitive: false
        quick: true
        partial: true
        algorithm: "prefix"
        external: {
            enable: false
            max_results: 100
            completer: null
        }
    }

    error_style: "fancy"

    hooks: {
        pre_execution: [{
            condition: {|| true }
            code: {|| |cmd|
                if ($env.NUSHELL_AUDIT_ENABLED? | default false) {
                    $"(date now | format date '%Y-%m-%d %H:%M:%S') - Command: ($cmd)" | save -a $env.NUSHELL_AUDIT_FILE
                }

                let blocked = ["rm", "mv", "cp", "chmod", "chown", "sudo", "su"]
                let cmd_name = ($cmd | split row " " | first)
                if $cmd_name in $blocked and ($env.NUSHELL_READONLY_MODE? | default true) {
                    error make {msg: $"Command '($cmd_name)' is blocked in read-only mode"}
                }
            }
        }]
    }

    menus: []
    keybindings: []
}

# Security aliases
alias ll = ls -la
alias df = df -h
alias free = free -h

print "🛡️  Nushell secure mode active"
EOF

    # Set proper ownership
    chown -R "$ADMIN_USER:$ADMIN_USER" "$USER_HOME/.config/nushell"
    chown -R "$ADMIN_USER:$ADMIN_USER" "$USER_HOME/nushell"

    success "Configuration created successfully"
}

# Install plugins (if enabled)
install_plugins() {
    if [[ "$NUSHELL_PLUGINS" != "true" ]]; then
        log "Plugin installation skipped (disabled)"
        return
    fi

    log "Installing Nushell plugins..."

    # KCL plugin (for configuration language support)
    if command -v kcl &> /dev/null; then
        log "KCL binary found, plugin support available"
    else
        warn "KCL binary not found. Install KCL for full configuration support."
    fi

    # Create plugin registration script
    cat > "$USER_HOME/nushell/scripts/register-plugins.nu" << 'EOF'
# Plugin registration script
# Run this to register available plugins

print "🔌 Registering Nushell plugins..."

try {
    if (which nu_plugin_kcl | is-not-empty) {
        plugin add nu_plugin_kcl
        print "✅ Registered nu_plugin_kcl"
    }
} catch {
    print "⚠️  Failed to register nu_plugin_kcl"
}

try {
    if (which nu_plugin_tera | is-not-empty) {
        plugin add nu_plugin_tera
        print "✅ Registered nu_plugin_tera"
    }
} catch {
    print "⚠️  Failed to register nu_plugin_tera"
}

try {
    if (which nu_plugin_polars | is-not-empty) {
        plugin add nu_plugin_polars
        print "✅ Registered nu_plugin_polars"
    }
} catch {
    print "⚠️  Failed to register nu_plugin_polars"
}

print "🔌 Plugin registration completed"
EOF

    chmod +x "$USER_HOME/nushell/scripts/register-plugins.nu"
    success "Plugin installation completed"
}

# Create systemd service (optional)
create_service() {
    if [[ ! -d "/etc/systemd/system" ]]; then
        log "Systemd not available, skipping service creation"
        return
    fi

    log "Creating Nushell monitoring service..."

    sudo tee "/etc/systemd/system/nushell-monitoring.service" > /dev/null << EOF
[Unit]
Description=Nushell Infrastructure Monitoring
After=network.target
Wants=network.target

[Service]
Type=simple
User=$ADMIN_USER
Group=$ADMIN_USER
WorkingDirectory=$USER_HOME/nushell
Environment=NUSHELL_EXECUTION_MODE=restricted
Environment=NUSHELL_READONLY_MODE=true
Environment=NUSHELL_AUDIT_ENABLED=true
ExecStart=$INSTALL_DIR/nu --config $USER_HOME/.config/nushell/config.nu --env-config $USER_HOME/.config/nushell/env.nu
Restart=always
RestartSec=10

# Security settings
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=read-only
ReadOnlyPaths=/

[Install]
WantedBy=multi-user.target
EOF

    sudo systemctl daemon-reload
    success "Systemd service created (disabled by default)"
}

# Verify installation
verify_installation() {
    log "Verifying Nushell installation..."

    # Check binary
    if ! command -v nu &> /dev/null; then
        error "Nushell binary not found in PATH"
        exit 1
    fi

    # Check version
    local installed_version=$(nu --version | awk '{print $2}')
    if [[ "$installed_version" != "$NUSHELL_VERSION" ]]; then
        warn "Version mismatch: expected $NUSHELL_VERSION, got $installed_version"
    else
        success "Nushell version $installed_version verified"
    fi

    # Test basic functionality
    if echo 'print "test"' | nu --config /dev/null &> /dev/null; then
        success "Basic functionality test passed"
    else
        error "Basic functionality test failed"
        exit 1
    fi

    # Check configuration files
    if [[ -f "$USER_HOME/.config/nushell/config.nu" ]] && [[ -f "$USER_HOME/.config/nushell/env.nu" ]]; then
        success "Configuration files created successfully"
    else
        error "Configuration files missing"
        exit 1
    fi

    success "Installation verification completed"
}

# Main installation process
main() {
    log "Starting Nushell Infrastructure Runtime installation..."
    log "Version: $NUSHELL_VERSION"
    log "Architecture: $NUSHELL_ARCH-$NUSHELL_OS"
    log "Install directory: $INSTALL_DIR"
    log "Security mode: readonly=$NUSHELL_READONLY, plugins=$NUSHELL_PLUGINS"

    check_prerequisites
    download_nushell
    create_configuration
    install_plugins
    create_service
    verify_installation

    success "🎉 Nushell Infrastructure Runtime installation completed successfully!"
    log ""
    log "Next steps:"
    log "1. Add $INSTALL_DIR to your PATH if not already present"
    log "2. Run 'nu' to start Nushell with secure configuration"
    log "3. Use 'nu $USER_HOME/nushell/scripts/register-plugins.nu' to register plugins (if enabled)"
    log "4. Enable monitoring service: sudo systemctl enable nushell-monitoring.service (optional)"
    log ""
    log "Configuration files:"
    log "- Config: $USER_HOME/.config/nushell/config.nu"
    log "- Environment: $USER_HOME/.config/nushell/env.nu"
    log "- Scripts: $USER_HOME/nushell/scripts/"
    log "- Audit log: $USER_HOME/nushell/audit.log"
}

# Run main function
main "$@"