#!/bin/bash

# MolnOS CLI - Main command-line interface for MolnOS
# This is the core CLI that gets installed to ~/.local/bin/molnos

set -e

VERSION="1.4.0"
INSTALL_DIR="$HOME/.molnos"
VERSION_FILE="$INSTALL_DIR/VERSION"
API_FILE="$INSTALL_DIR/molnos_core.mjs"
CONFIG_DIR="$HOME/.molnos"
TOKEN_FILE="$CONFIG_DIR/token"
REFRESH_TOKEN_FILE="$CONFIG_DIR/refresh_token"
CONFIG_URL_FILE="$CONFIG_DIR/api_url"

# Global token override (set by --token flag)
EXPLICIT_TOKEN=""

# Global force flag (set by --force flag to skip confirmations)
FORCE_FLAG=false

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

print_error() {
    echo -e "${RED}Error: $1${NC}" >&2
}

print_success() {
    echo -e "${GREEN}$1${NC}"
}

print_info() {
    echo -e "${YELLOW}$1${NC}"
}

print_json() {
    echo -e "${BLUE}$1${NC}"
}

# Prompts for user confirmation (returns 0 if yes, 1 if no)
confirm() {
    local prompt="${1:-Are you sure?}"
    local default="${2:-n}"

    if [[ "$default" == "y" ]]; then
        read -r -p "$prompt [Y/n]: " response
        case "$response" in
            [nN][oO]|[nN]) return 1 ;;
            *) return 0 ;;
        esac
    else
        read -r -p "$prompt [y/N]: " response
        case "$response" in
            [yY][eE][sS]|[yY]) return 0 ;;
            *) return 1 ;;
        esac
    fi
}

# ============================================================================
# Authentication & HTTP Helpers
# ============================================================================

ensure_config_dir() {
    mkdir -p "$CONFIG_DIR"
}

save_token() {
    ensure_config_dir
    echo "$1" > "$TOKEN_FILE"
    chmod 600 "$TOKEN_FILE"
}

save_refresh_token() {
    ensure_config_dir
    echo "$1" > "$REFRESH_TOKEN_FILE"
    chmod 600 "$REFRESH_TOKEN_FILE"
}

get_refresh_token() {
    if [ -f "$REFRESH_TOKEN_FILE" ]; then
        cat "$REFRESH_TOKEN_FILE"
        return
    fi
    echo ""
}

get_token() {
    # Credential chain priority (similar to AWS/GCP SDKs):
    # 1. Explicit --token flag (highest priority)
    # 2. MOLNOS_TOKEN environment variable
    # 3. Token file (~/.molnos/token)
    # 4. MOLNOS_SERVICE_ACCOUNT_KEY environment variable (lowest priority)

    # 1. Check for explicit --token flag
    if [ -n "$EXPLICIT_TOKEN" ]; then
        echo "$EXPLICIT_TOKEN"
        return
    fi

    # 2. Check MOLNOS_TOKEN environment variable
    if [ -n "${MOLNOS_TOKEN:-}" ]; then
        echo "$MOLNOS_TOKEN"
        return
    fi

    # 3. Check token file (current behavior)
    if [ -f "$TOKEN_FILE" ]; then
        cat "$TOKEN_FILE"
        return
    fi

    # 4. Check service account key environment variable
    if [ -n "${MOLNOS_SERVICE_ACCOUNT_KEY:-}" ]; then
        echo "$MOLNOS_SERVICE_ACCOUNT_KEY"
        return
    fi

    # No credentials found
    echo ""
}

get_token_source() {
    # Returns the source of the current token for debugging/status
    if [ -n "$EXPLICIT_TOKEN" ]; then
        echo "explicit --token flag"
    elif [ -n "${MOLNOS_TOKEN:-}" ]; then
        echo "MOLNOS_TOKEN environment variable"
    elif [ -f "$TOKEN_FILE" ]; then
        echo "token file ($TOKEN_FILE)"
    elif [ -n "${MOLNOS_SERVICE_ACCOUNT_KEY:-}" ]; then
        echo "MOLNOS_SERVICE_ACCOUNT_KEY environment variable"
    else
        echo "none (not authenticated)"
    fi
}

clear_token() {
    if [ -f "$TOKEN_FILE" ]; then
        rm "$TOKEN_FILE"
    fi
}

get_api_url() {
    # Returns the API URL using priority chain:
    # 1. MOLNOS_API_URL environment variable
    # 2. Configured URL file (~/.molnos/api_url)
    # 3. Default (http://localhost:3000)

    # 1. Check MOLNOS_API_URL environment variable
    if [ -n "${MOLNOS_API_URL:-}" ]; then
        echo "$MOLNOS_API_URL"
        return
    fi

    # 2. Check configured URL file
    if [ -f "$CONFIG_URL_FILE" ]; then
        cat "$CONFIG_URL_FILE"
        return
    fi

    # 3. Default
    echo "http://localhost:3000"
}

set_api_url() {
    local url="$1"

    if [ -z "$url" ]; then
        print_error "URL cannot be empty"
        return 1
    fi

    # Basic validation - ensure it starts with http:// or https://
    if [[ ! "$url" =~ ^https?:// ]]; then
        print_error "URL must start with http:// or https://"
        return 1
    fi

    # Remove trailing slash if present
    url="${url%/}"

    # Ensure config directory exists
    mkdir -p "$CONFIG_DIR"

    # Save URL to file
    echo "$url" > "$CONFIG_URL_FILE"
    print_success "API URL configured: $url"
}

get_api_url_source() {
    # Returns the source of the current API URL for debugging/status
    if [ -n "${MOLNOS_API_URL:-}" ]; then
        echo "MOLNOS_API_URL environment variable"
    elif [ -f "$CONFIG_URL_FILE" ]; then
        echo "configured file ($CONFIG_URL_FILE)"
    else
        echo "default (http://localhost:3000)"
    fi
}

# Initialize API_URL using the priority chain
API_URL=$(get_api_url)

clear_refresh_token() {
    if [ -f "$REFRESH_TOKEN_FILE" ]; then
        rm "$REFRESH_TOKEN_FILE"
    fi
}

# Attempt to refresh the access token using the stored refresh token
# Returns 0 on success, 1 on failure
attempt_token_refresh() {
    local refresh_token=$(get_refresh_token)

    # Can't refresh without a refresh token
    if [ -z "$refresh_token" ]; then
        return 1
    fi

    # Don't print info during automatic refresh to avoid cluttering output
    local response
    if command -v curl &> /dev/null; then
        response=$(curl -sSL -X POST -H "Content-Type: application/json" -d "{\"refreshToken\":\"$refresh_token\"}" "$API_URL/auth/refresh" 2>/dev/null)
    elif command -v wget &> /dev/null; then
        response=$(wget -q -O - --post-data="{\"refreshToken\":\"$refresh_token\"}" --header="Content-Type: application/json" "$API_URL/auth/refresh" 2>/dev/null)
    else
        return 1
    fi

    # Extract new access token and optionally new refresh token
    if command -v node &> /dev/null; then
        local new_access_token=$(echo "$response" | node -e "try { const data=JSON.parse(require('fs').readFileSync(0,'utf8')); console.log(data.accessToken || ''); } catch(e) { console.log(''); }" 2>/dev/null)
        local new_refresh_token=$(echo "$response" | node -e "try { const data=JSON.parse(require('fs').readFileSync(0,'utf8')); console.log(data.refreshToken || ''); } catch(e) { console.log(''); }" 2>/dev/null)

        if [ -n "$new_access_token" ]; then
            save_token "$new_access_token"
            # Some APIs rotate refresh tokens, update if we got a new one
            if [ -n "$new_refresh_token" ]; then
                save_refresh_token "$new_refresh_token"
            fi
            return 0
        fi
    fi

    return 1
}

http_get() {
    local url="$1"
    local token=$(get_token)
    local retry="${2:-true}"  # Internal param to prevent infinite retry loop

    local response
    local http_code

    if command -v curl &> /dev/null; then
        if [ -n "$token" ]; then
            # Capture both response and HTTP status code
            response=$(curl -sSL -w "\n%{http_code}" -H "Authorization: Bearer $token" "$API_URL$url")
            http_code=$(echo "$response" | tail -n 1)
            response=$(echo "$response" | sed '$d')
        else
            curl -sSL "$API_URL$url"
            return
        fi
    elif command -v wget &> /dev/null; then
        if [ -n "$token" ]; then
            # wget doesn't easily provide status codes, so we'll just try the request
            response=$(wget -q -O - --header="Authorization: Bearer $token" "$API_URL$url" 2>&1)
            # Simple check: if response contains "401" or "Unauthorized", treat as 401
            if echo "$response" | grep -qi "401\|unauthorized"; then
                http_code="401"
            else
                echo "$response"
                return
            fi
        else
            wget -q -O - "$API_URL$url"
            return
        fi
    else
        print_error "Neither curl nor wget is available"
        exit 1
    fi

    # If we got a 401 and haven't already retried, attempt token refresh
    if [ "$http_code" = "401" ] && [ "$retry" = "true" ]; then
        if attempt_token_refresh; then
            # Retry the request with the new token (set retry=false to prevent loops)
            http_get "$url" false
            return
        fi
    fi

    # Return the response
    echo "$response"
}

http_post() {
    local url="$1"
    local data="$2"
    local token=$(get_token)
    local retry="${3:-true}"  # Internal param to prevent infinite retry loop

    local response
    local http_code

    if command -v curl &> /dev/null; then
        if [ -n "$token" ]; then
            # Capture both response and HTTP status code
            response=$(curl -sSL -w "\n%{http_code}" -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $token" -d "$data" "$API_URL$url")
            http_code=$(echo "$response" | tail -n 1)
            response=$(echo "$response" | sed '$d')
        else
            curl -sSL -X POST -H "Content-Type: application/json" -d "$data" "$API_URL$url"
            return
        fi
    elif command -v wget &> /dev/null; then
        if [ -n "$token" ]; then
            response=$(wget -q -O - --post-data="$data" --header="Content-Type: application/json" --header="Authorization: Bearer $token" "$API_URL$url" 2>&1)
            if echo "$response" | grep -qi "401\|unauthorized"; then
                http_code="401"
            else
                echo "$response"
                return
            fi
        else
            wget -q -O - --post-data="$data" --header="Content-Type: application/json" "$API_URL$url"
            return
        fi
    else
        print_error "Neither curl nor wget is available"
        exit 1
    fi

    # If we got a 401 and haven't already retried, attempt token refresh
    if [ "$http_code" = "401" ] && [ "$retry" = "true" ]; then
        if attempt_token_refresh; then
            # Retry the request with the new token (set retry=false to prevent loops)
            http_post "$url" "$data" false
            return
        fi
    fi

    # Return the response
    echo "$response"
}

http_put() {
    local url="$1"
    local data="$2"
    local token=$(get_token)
    local retry="${3:-true}"  # Internal param to prevent infinite retry loop

    local response
    local http_code

    if command -v curl &> /dev/null; then
        if [ -n "$token" ]; then
            # Capture both response and HTTP status code
            response=$(curl -sSL -w "\n%{http_code}" -X PUT -H "Content-Type: application/json" -H "Authorization: Bearer $token" -d "$data" "$API_URL$url")
            http_code=$(echo "$response" | tail -n 1)
            response=$(echo "$response" | sed '$d')

            # If we got a 401 and haven't already retried, attempt token refresh
            if [ "$http_code" = "401" ] && [ "$retry" = "true" ]; then
                if attempt_token_refresh; then
                    http_put "$url" "$data" false
                    return
                fi
            fi

            echo "$response"
        else
            curl -sSL -X PUT -H "Content-Type: application/json" -d "$data" "$API_URL$url"
        fi
    else
        print_error "PUT requests require curl"
        exit 1
    fi
}

http_patch() {
    local url="$1"
    local data="$2"
    local token=$(get_token)
    local retry="${3:-true}"  # Internal param to prevent infinite retry loop

    local response
    local http_code

    if command -v curl &> /dev/null; then
        if [ -n "$token" ]; then
            # Capture both response and HTTP status code
            response=$(curl -sSL -w "\n%{http_code}" -X PATCH -H "Content-Type: application/json" -H "Authorization: Bearer $token" -d "$data" "$API_URL$url")
            http_code=$(echo "$response" | tail -n 1)
            response=$(echo "$response" | sed '$d')

            # If we got a 401 and haven't already retried, attempt token refresh
            if [ "$http_code" = "401" ] && [ "$retry" = "true" ]; then
                if attempt_token_refresh; then
                    http_patch "$url" "$data" false
                    return
                fi
            fi

            echo "$response"
        else
            curl -sSL -X PATCH -H "Content-Type: application/json" -d "$data" "$API_URL$url"
        fi
    else
        print_error "PATCH requests require curl"
        exit 1
    fi
}

http_delete() {
    local url="$1"
    local data="${2:-}"
    local token=$(get_token)
    local retry="${3:-true}"  # Internal param to prevent infinite retry loop

    local response
    local http_code

    if command -v curl &> /dev/null; then
        if [ -n "$token" ]; then
            # Capture both response and HTTP status code
            if [ -n "$data" ]; then
                response=$(curl -sSL -w "\n%{http_code}" -X DELETE -H "Content-Type: application/json" -H "Authorization: Bearer $token" -d "$data" "$API_URL$url")
            else
                response=$(curl -sSL -w "\n%{http_code}" -X DELETE -H "Authorization: Bearer $token" "$API_URL$url")
            fi
            http_code=$(echo "$response" | tail -n 1)
            response=$(echo "$response" | sed '$d')

            # If we got a 401 and haven't already retried, attempt token refresh
            if [ "$http_code" = "401" ] && [ "$retry" = "true" ]; then
                if attempt_token_refresh; then
                    http_delete "$url" "$data" false
                    return
                fi
            fi

            echo "$response"
        else
            # No token case
            if [ -n "$data" ]; then
                curl -sSL -X DELETE -H "Content-Type: application/json" -d "$data" "$API_URL$url"
            else
                curl -sSL -X DELETE "$API_URL$url"
            fi
        fi
    else
        print_error "DELETE requests require curl"
        exit 1
    fi
}

check_node() {
    if ! command -v node &> /dev/null; then
        print_error "Node.js is not installed"
        echo "Please install Node.js 24 or later from https://nodejs.org/"
        exit 1
    fi

    NODE_VERSION=$(node -v | cut -d 'v' -f 2 | cut -d '.' -f 1)
    if [ "$NODE_VERSION" -lt 24 ]; then
        print_error "Node.js version 24 or later is required (found v$NODE_VERSION)"
        echo "Please upgrade Node.js from https://nodejs.org/"
        exit 1
    fi
}

# ============================================================================
# Health Check
# ============================================================================

molnos_health() {
    print_info "Checking MolnOS Core health..."
    response=$(http_get "/health")
    echo "$response"
}

# ============================================================================
# Authentication Commands
# ============================================================================

molnos_login() {
    local email="$1"

    if [ -z "$email" ]; then
        print_error "Email is required"
        echo "Usage: molnos auth login <email>"
        exit 1
    fi

    # Magic link flow - always use /auth/login endpoint
    print_info "Requesting magic link for $email..."
    response=$(http_post "/auth/login" "{\"email\":\"$email\"}")

    # Show response and instructions
    print_json "$response"
    print_info "A magic link has been sent to $email"
    print_info "Use 'molnos auth verify <token> $email' to complete authentication"
}

molnos_verify() {
    local token="$1"
    local email="$2"

    if [ -z "$token" ] || [ -z "$email" ]; then
        print_error "Token and email are required"
        echo "Usage: molnos auth verify <token> <email>"
        exit 1
    fi

    print_info "Verifying magic link..."
    response=$(http_get "/auth/verify?token=$token&email=$email")

    # Extract access token and refresh token from response
    if command -v node &> /dev/null; then
        access_token=$(echo "$response" | node -e "const data=JSON.parse(require('fs').readFileSync(0,'utf8')); console.log(data.accessToken || '')")
        refresh_token=$(echo "$response" | node -e "const data=JSON.parse(require('fs').readFileSync(0,'utf8')); console.log(data.refreshToken || '')")

        if [ -n "$access_token" ]; then
            save_token "$access_token"
            if [ -n "$refresh_token" ]; then
                save_refresh_token "$refresh_token"
                print_success "Authentication successful! Access token and refresh token saved."
            else
                print_success "Authentication successful! Access token saved."
            fi
        else
            print_error "Failed to extract token from response"
        fi
    fi

    print_json "$response"
}

molnos_refresh() {
    local refresh_token="$1"

    if [ -z "$refresh_token" ]; then
        print_error "Refresh token is required"
        echo "Usage: molnos auth refresh <refresh_token>"
        exit 1
    fi

    print_info "Refreshing access token..."
    response=$(http_post "/auth/refresh" "{\"refreshToken\":\"$refresh_token\"}")

    # Extract new access token
    if command -v node &> /dev/null; then
        access_token=$(echo "$response" | node -e "const data=JSON.parse(require('fs').readFileSync(0,'utf8')); console.log(data.accessToken || '')")

        if [ -n "$access_token" ]; then
            save_token "$access_token"
            print_success "Token refreshed and saved."
        fi
    fi

    print_json "$response"
}

molnos_logout() {
    clear_token
    clear_refresh_token
    print_success "Logged out. Tokens cleared."
}

molnos_whoami() {
    print_info "Getting current identity..."
    response=$(http_get "/identity/whoami")
    print_json "$response"
}

molnos_auth_status() {
    local token=$(get_token)
    local source=$(get_token_source)

    print_info "Authentication Status"
    echo ""
    echo "  Credential Source: $source"

    if [ -n "$token" ]; then
        # Show partial token for verification (first 10 chars)
        local token_preview="${token:0:10}..."
        echo "  Token Preview:     $token_preview"
        print_success "  Status:            Authenticated"
    else
        print_error "  Status:            Not authenticated"
        echo ""
        print_info "To authenticate, use one of the following methods:"
        echo "  1. Run: molnos auth login <email>"
        echo "  2. Set environment variable: export MOLNOS_TOKEN=<your-token>"
        echo "  3. Use --token flag: molnos --token <your-token> <command>"
        echo "  4. Use service account: export MOLNOS_SERVICE_ACCOUNT_KEY=<sa-key>"
    fi
    echo ""
}

molnos_auth_configure() {
    print_info "MolnOS Authentication Configuration"
    echo ""
    echo "How would you like to authenticate?"
    echo ""
    echo "  1) Magic Link (interactive - recommended for users)"
    echo "  2) Environment Variable (recommended for CI/CD)"
    echo "  3) Service Account (recommended for automation)"
    echo "  4) Manual Token Entry"
    echo ""

    read -r -p "Choose an option [1-4]: " choice
    echo ""

    case "$choice" in
        1)
            read -r -p "Enter your email address: " email
            if [ -z "$email" ]; then
                print_error "Email is required"
                exit 1
            fi
            print_info "Requesting magic link for $email..."
            molnos_login "$email"
            echo ""
            print_info "Check your email for the magic link, then run:"
            echo "  molnos auth verify <token> $email"
            ;;
        2)
            print_info "To use environment variables, add to your shell profile:"
            echo ""
            echo "  export MOLNOS_TOKEN=<your-token>"
            echo "  export MOLNOS_API_URL=<api-url>  # Optional, defaults to http://localhost:3000"
            echo ""
            print_info "For CI/CD, you can also use:"
            echo "  export MOLNOS_SERVICE_ACCOUNT_KEY=<sa-key>"
            echo ""
            read -r -p "Would you like to set MOLNOS_TOKEN now? [y/N]: " set_env
            if [[ "$set_env" =~ ^[Yy]$ ]]; then
                read -r -p "Enter your token: " token
                if [ -n "$token" ]; then
                    echo ""
                    print_info "Add this to your ~/.bashrc or ~/.zshrc:"
                    echo "  export MOLNOS_TOKEN=$token"
                    echo ""
                    print_info "Or set it temporarily for this session:"
                    echo "  export MOLNOS_TOKEN=$token"
                fi
            fi
            ;;
        3)
            print_info "To create a service account:"
            echo "  1. Authenticate first (using option 1 or 4)"
            echo "  2. Run: molnos service-accounts create <name> <description> <role>"
            echo "  3. Copy the API key (format: sa.<id>.<key>)"
            echo "  4. Set environment variable:"
            echo "       export MOLNOS_SERVICE_ACCOUNT_KEY=<api-key>"
            echo ""
            ;;
        4)
            read -r -p "Enter your access token: " token
            if [ -z "$token" ]; then
                print_error "Token is required"
                exit 1
            fi
            save_token "$token"
            print_success "Token saved to $TOKEN_FILE"
            echo ""
            print_info "You can now use MolnOS CLI commands"
            ;;
        *)
            print_error "Invalid option"
            exit 1
            ;;
    esac
}

molnos_oauth_providers() {
    print_info "Listing available OAuth providers..."
    response=$(http_get "/auth/oauth/providers")
    print_json "$response"
}

molnos_oauth_initiate() {
    local provider="$1"
    local redirect_uri="$2"

    if [ -z "$provider" ]; then
        print_error "Provider ID is required"
        echo ""
        echo "Usage: molnos auth oauth initiate <provider-id> [redirect-uri]"
        echo ""
        echo "Examples:"
        echo "  molnos auth oauth initiate google"
        echo "  molnos auth oauth initiate github http://localhost:3000/callback"
        echo ""
        echo "To see available providers, run:"
        echo "  molnos auth oauth providers"
        exit 1
    fi

    print_info "Initiating OAuth flow with provider: $provider"

    local body="{}"
    if [ -n "$redirect_uri" ]; then
        body=$(printf '{"redirectUri":"%s"}' "$redirect_uri")
    fi

    response=$(http_post "/auth/oauth/$provider" "$body")
    print_json "$response"

    # Extract authorization URL from response if available
    local auth_url
    auth_url=$(echo "$response" | grep -o '"authorizationUrl":"[^"]*"' | sed 's/"authorizationUrl":"\([^"]*\)"/\1/')
    if [ -n "$auth_url" ]; then
        echo ""
        print_info "Open this URL in your browser to continue:"
        echo "  $auth_url"
    fi
}

molnos_oauth_callback() {
    local provider="$1"
    local code="$2"
    local state="$3"

    if [ -z "$provider" ] || [ -z "$code" ]; then
        print_error "Provider ID and authorization code are required"
        echo ""
        echo "Usage: molnos auth oauth callback <provider-id> <code> [state]"
        echo ""
        echo "This command is typically called automatically by the OAuth flow."
        echo "You may need to extract the 'code' parameter from the callback URL."
        exit 1
    fi

    print_info "Processing OAuth callback for provider: $provider"

    local query="code=$code"
    if [ -n "$state" ]; then
        query="$query&state=$state"
    fi

    response=$(http_get "/auth/oauth/$provider/callback?$query")
    print_json "$response"

    # Extract and save token if present
    local token
    token=$(echo "$response" | grep -o '"accessToken":"[^"]*"' | sed 's/"accessToken":"\([^"]*\)"/\1/')
    if [ -n "$token" ]; then
        save_token "$token"
        print_success "Authentication successful! Token saved."
    fi
}

# ============================================================================
# Configuration Commands
# ============================================================================

molnos_configure_url() {
    local url="$1"

    if [ -z "$url" ]; then
        # Show current configuration
        local current_url=$(get_api_url)
        local source=$(get_api_url_source)

        echo "Current API URL: $current_url"
        echo "Source: $source"
        echo ""
        echo "Usage: molnos configure url <URL>"
        echo ""
        echo "Example:"
        echo "  molnos configure url https://api.molnos.cloud/prod"
        echo ""
        echo "To reset to default, use:"
        echo "  molnos configure url http://localhost:3000"
        exit 0
    fi

    set_api_url "$url"
}

# ============================================================================
# Server Management Commands
# ============================================================================

molnos_install() {
    print_info "Installing MolnOS Core..."
    check_node

    # Create installation directory
    mkdir -p "$INSTALL_DIR"

    # Download latest version
    print_info "Downloading latest version from releases.molnos.cloud..."
    TEMP_FILE="/tmp/molnos_core_latest.zip"

    if command -v curl &> /dev/null; then
        curl -sSL -o "$TEMP_FILE" "https://releases.molnos.cloud/molnos_core_latest.zip"
    elif command -v wget &> /dev/null; then
        wget -q -O "$TEMP_FILE" "https://releases.molnos.cloud/molnos_core_latest.zip"
    else
        print_error "Neither curl nor wget is available"
        exit 1
    fi

    # Extract the archive
    print_info "Extracting files..."
    TEMP_EXTRACT="/tmp/molnos_extract_$$"
    mkdir -p "$TEMP_EXTRACT"

    if command -v unzip &> /dev/null; then
        unzip -q -o "$TEMP_FILE" -d "$TEMP_EXTRACT"
    else
        print_error "unzip is not installed"
        exit 1
    fi

    rm "$TEMP_FILE"

    # Find the actual files (handle nested directories)
    if [ -f "$TEMP_EXTRACT/molnos_core.mjs" ]; then
        cp -r "$TEMP_EXTRACT"/* "$INSTALL_DIR/"
    else
        SUBDIR=$(find "$TEMP_EXTRACT" -name "molnos_core.mjs" -type f | head -n 1 | xargs dirname)
        if [ -n "$SUBDIR" ]; then
            cp -r "$SUBDIR"/* "$INSTALL_DIR/"
        else
            print_error "Could not find molnos_core.mjs in the downloaded archive"
            rm -rf "$TEMP_EXTRACT"
            exit 1
        fi
    fi

    rm -rf "$TEMP_EXTRACT"

    # Verify installation
    if [ ! -f "$API_FILE" ]; then
        print_error "Installation failed: molnos_core.mjs not found after extraction"
        exit 1
    fi

    # Check if VERSION file exists
    if [ -f "$VERSION_FILE" ]; then
        INSTALLED_VERSION=$(cat "$VERSION_FILE")
        print_success "MolnOS Core v$INSTALLED_VERSION installed successfully!"
    else
        print_success "MolnOS Core installed successfully!"
    fi

    echo ""
    print_info "Run 'molnos start' to start the API server"
}

molnos_upgrade() {
    local component="${1:-all}"  # all, core, or cli

    case "$component" in
        all)
            print_info "Upgrading both MolnOS Core and CLI..."
            molnos_upgrade_core
            echo ""
            molnos_upgrade_cli
            ;;
        core)
            molnos_upgrade_core
            ;;
        cli)
            molnos_upgrade_cli
            ;;
        *)
            print_error "Invalid component: $component"
            echo "Usage: molnos upgrade [all|core|cli]"
            echo "  all   - Upgrade both Core and CLI (default)"
            echo "  core  - Upgrade only MolnOS Core"
            echo "  cli   - Upgrade only the CLI tool"
            exit 1
            ;;
    esac
}

molnos_upgrade_core() {
    print_info "Checking for updates to the MolnOS Core..."

    # Check if MolnOS is installed
    if [ ! -d "$INSTALL_DIR" ]; then
        print_error "MolnOS Core is not installed. Run 'molnos install' first."
        exit 1
    fi

    # Get current version
    CURRENT_VERSION=""
    if [ -f "$VERSION_FILE" ]; then
        CURRENT_VERSION=$(cat "$VERSION_FILE" | tr -d '[:space:]')
        print_info "Current Core version: v$CURRENT_VERSION"
    else
        print_info "No version file found. Assuming fresh install needed."
    fi

    # Check latest version from API
    print_info "Checking latest Core version from api.molnos.cloud..."

    if command -v curl &> /dev/null; then
        VERSION_JSON=$(curl -sSL "https://api.molnos.cloud/prod/version/core")
    elif command -v wget &> /dev/null; then
        VERSION_JSON=$(wget -q -O - "https://api.molnos.cloud/prod/version/core")
    else
        print_error "Neither curl nor wget is available"
        exit 1
    fi

    # Parse JSON to extract version field
    if command -v node &> /dev/null; then
        LATEST_VERSION=$(echo "$VERSION_JSON" | node -e "console.log(JSON.parse(require('fs').readFileSync(0,'utf8')).version)")
    else
        LATEST_VERSION=$(echo "$VERSION_JSON" | grep -o '"version"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*"\([^"]*\)"$/\1/')
    fi

    LATEST_VERSION=$(echo "$LATEST_VERSION" | tr -d '[:space:]')
    print_info "Latest Core version: v$LATEST_VERSION"

    # Compare versions
    if [ -z "$CURRENT_VERSION" ]; then
        print_info "Installing latest Core version..."
        molnos_install
    elif [ "$CURRENT_VERSION" = "$LATEST_VERSION" ]; then
        print_success "You already have the latest Core version (v$CURRENT_VERSION)"
    else
        print_info "Upgrading Core from v$CURRENT_VERSION to v$LATEST_VERSION..."
        molnos_install
    fi
}

molnos_upgrade_cli() {
    print_info "Checking for updates to the MolnOS CLI..."

    # Get current CLI version
    CURRENT_CLI_VERSION="$VERSION"
    print_info "Current CLI version: v$CURRENT_CLI_VERSION"

    # Check latest CLI version from API
    print_info "Checking latest CLI version from api.molnos.cloud..."

    if command -v curl &> /dev/null; then
        CLI_VERSION_JSON=$(curl -sSL "https://api.molnos.cloud/prod/version/cli")
    elif command -v wget &> /dev/null; then
        CLI_VERSION_JSON=$(wget -q -O - "https://api.molnos.cloud/prod/version/cli")
    else
        print_error "Neither curl nor wget is available"
        exit 1
    fi

    # Parse JSON to extract version field
    if command -v node &> /dev/null; then
        LATEST_CLI_VERSION=$(echo "$CLI_VERSION_JSON" | node -e "console.log(JSON.parse(require('fs').readFileSync(0,'utf8')).version)")
    else
        LATEST_CLI_VERSION=$(echo "$CLI_VERSION_JSON" | grep -o '"version"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*"\([^"]*\)"$/\1/')
    fi

    LATEST_CLI_VERSION=$(echo "$LATEST_CLI_VERSION" | tr -d '[:space:]')
    print_info "Latest CLI version: v$LATEST_CLI_VERSION"

    # Compare versions
    if [ "$CURRENT_CLI_VERSION" = "$LATEST_CLI_VERSION" ]; then
        print_success "You already have the latest CLI version (v$CURRENT_CLI_VERSION)"
        return
    fi

    print_info "Upgrading CLI from v$CURRENT_CLI_VERSION to v$LATEST_CLI_VERSION..."

    # Download and install new CLI
    BIN_DIR="$HOME/.local/bin"
    TEMP_CLI="/tmp/molnos_cli_new_$$"

    print_info "Downloading latest CLI from molnos.cloud..."

    if command -v curl &> /dev/null; then
        curl -sSL -o "$TEMP_CLI" "https://releases.molnos.cloud/molnos-cli.sh"
    elif command -v wget &> /dev/null; then
        wget -q -O "$TEMP_CLI" "https://releases.molnos.cloud/molnos-cli.sh"
    else
        print_error "Neither curl nor wget is available"
        exit 1
    fi

    # Backup current CLI
    if [ -f "$BIN_DIR/molnos" ]; then
        BACKUP_FILE="$BIN_DIR/molnos.backup.$(date +%s)"
        cp "$BIN_DIR/molnos" "$BACKUP_FILE"
        print_info "Backed up current CLI to $BACKUP_FILE"
    fi

    # Install new CLI
    chmod +x "$TEMP_CLI"
    mv "$TEMP_CLI" "$BIN_DIR/molnos"

    print_success "CLI upgraded successfully to v$LATEST_CLI_VERSION!"
    echo ""
    print_info "Restart your shell or run 'hash -r' to use the new version"

    # Optionally upgrade the installer script too
    upgrade_installer_script
}

upgrade_installer_script() {
    print_info "Checking for installer script update..."

    # Try to find installer script in common locations
    local installer_locations=(
        "$HOME/.molnos/install.sh"
        "$HOME/molnos-cli/install.sh"
        "./install.sh"
    )

    local installer_found=false
    local installer_path=""

    for location in "${installer_locations[@]}"; do
        if [ -f "$location" ]; then
            installer_found=true
            installer_path="$location"
            break
        fi
    done

    if [ "$installer_found" = false ]; then
        print_info "Installer script not found locally. Skipping installer update."
        return
    fi

    print_info "Downloading latest installer script..."

    TEMP_INSTALLER="/tmp/molnos_install_new_$$"

    if command -v curl &> /dev/null; then
        if curl -sSL -o "$TEMP_INSTALLER" "https://releases.molnos.cloud/install.sh" 2>/dev/null; then
            chmod +x "$TEMP_INSTALLER"
            cp "$TEMP_INSTALLER" "$installer_path"
            rm "$TEMP_INSTALLER"
            print_success "Installer script updated at $installer_path"
        else
            print_info "Could not download installer update (optional)"
        fi
    elif command -v wget &> /dev/null; then
        if wget -q -O "$TEMP_INSTALLER" "https://releases.molnos.cloud/install.sh" 2>/dev/null; then
            chmod +x "$TEMP_INSTALLER"
            cp "$TEMP_INSTALLER" "$installer_path"
            rm "$TEMP_INSTALLER"
            print_success "Installer script updated at $installer_path"
        else
            print_info "Could not download installer update (optional)"
        fi
    fi
}

molnos_uninstall() {
    print_info "This will remove MolnOS Core and CLI from your system."
    echo ""

    if [ "$FORCE_FLAG" != "true" ]; then
        if ! confirm "Are you sure you want to uninstall MolnOS?"; then
            print_info "Uninstall cancelled."
            exit 0
        fi
    fi

    print_info "Uninstalling MolnOS..."

    if [ -d "$INSTALL_DIR" ]; then
        rm -rf "$INSTALL_DIR"
        print_success "MolnOS Core removed from $INSTALL_DIR"
    else
        print_info "MolnOS Core directory not found"
    fi

    # Remove the CLI itself
    if [ -f "$HOME/.local/bin/molnos" ]; then
        rm "$HOME/.local/bin/molnos"
        print_success "MolnOS CLI removed"
    fi

    print_success "MolnOS has been uninstalled"
    echo ""
    print_info "You may need to restart your shell or run 'hash -r' to clear the command cache"
}

molnos_start() {
    if [ ! -f "$API_FILE" ]; then
        print_error "MolnOS Core not found. Run 'molnos install' first."
        exit 1
    fi

    check_node

    print_info "Starting MolnOS Core..."

    USER_CWD="$PWD"
    export MOLNOS_USER_CWD="$USER_CWD"
    cd "$INSTALL_DIR"

    MOLNOS_USER_CWD="$USER_CWD" node molnos_core.mjs "$@"
}

# ============================================================================
# Configuration Commands
# ============================================================================

molnos_init() {
    print_info "Creating molnos.config.json..."

    cat > "molnos.config.json" << 'CONFIGEOF'
{
    "email": {
        "emailSubject": "Sign In To MolnOS",
        "user": "my_user@my_domain.net",
        "password": "my_password",
        "host": "smtp.my_host.net",
        "port": 465,
        "secure": true
    },
    "molnos": {
        "dataPath": "data",
        "initialUser": {
            "userName": "User",
            "email": "me@my_domain.net"
        }
    },
    "auth": {
        "jwtSecret": "your-jwt-secret",
        "consoleUrl": "https://localhost:8000"
    },
    "server": {
        "allowedDomains": [
            "*"
        ]
    }
}
CONFIGEOF

    print_success "molnos.config.json created successfully!"
    print_info "Edit the file to configure your MolnOS installation"
    echo ""
}

# ============================================================================
# Application Management Commands
# ============================================================================

molnos_apps_list() {
    print_info "Listing applications..."
    response=$(http_get "/applications")
    print_json "$response"
}

molnos_app_create() {
    local name="$1"
    local description="$2"
    shift 2
    local redirect_uris=()

    if [ -z "$name" ]; then
        print_error "Application name is required"
        echo "Usage: molnos apps create <name> <description> <redirect_uri_1> [redirect_uri_2 ...]"
        exit 1
    fi

    if [ -z "$description" ]; then
        print_error "Application description is required"
        echo "Usage: molnos apps create <name> <description> <redirect_uri_1> [redirect_uri_2 ...]"
        exit 1
    fi

    # Collect all remaining arguments as redirect URIs
    while [ $# -gt 0 ]; do
        redirect_uris+=("$1")
        shift
    done

    if [ ${#redirect_uris[@]} -eq 0 ]; then
        print_error "At least one redirect URI is required"
        echo "Usage: molnos apps create <name> <description> <redirect_uri_1> [redirect_uri_2 ...]"
        exit 1
    fi

    # Build JSON array for redirect URIs
    redirect_uris_json=$(printf '"%s",' "${redirect_uris[@]}")
    redirect_uris_json="[${redirect_uris_json%,}]"

    print_info "Creating application '$name'..."
    response=$(http_post "/applications" "{\"name\":\"$name\",\"description\":\"$description\",\"redirectUris\":$redirect_uris_json}")
    print_json "$response"
}

molnos_app_get() {
    local app_id="$1"

    if [ -z "$app_id" ]; then
        print_error "Application ID is required"
        echo "Usage: molnos apps get <app_id>"
        exit 1
    fi

    print_info "Getting application $app_id..."
    response=$(http_get "/applications/$app_id")
    print_json "$response"
}

molnos_app_update() {
    local app_id="$1"
    local data="$2"

    if [ -z "$app_id" ] || [ -z "$data" ]; then
        print_error "Application ID and JSON data are required"
        echo "Usage: molnos apps update <app_id> '<json_data>'"
        echo "Example: molnos apps update abc123 '{\"name\":\"New Name\",\"redirectUris\":[\"https://example.com/callback\"]}'"
        exit 1
    fi

    print_info "Updating application $app_id..."
    response=$(http_patch "/applications/$app_id" "$data")
    print_json "$response"
}

molnos_app_delete() {
    local app_id="$1"

    if [ -z "$app_id" ]; then
        print_error "Application ID is required"
        echo "Usage: molnos apps delete <app_id>"
        exit 1
    fi

    if [ "$FORCE_FLAG" != "true" ]; then
        if ! confirm "Delete application $app_id? This action cannot be undone."; then
            print_info "Deletion cancelled."
            exit 0
        fi
    fi

    print_info "Deleting application $app_id..."
    response=$(http_delete "/applications/$app_id")
    print_json "$response"
}

# ============================================================================
# Identity Management Commands
# ============================================================================

molnos_identities_list() {
    print_info "Listing all identities..."
    response=$(http_get "/identity/identities")
    print_json "$response"
}

molnos_users_list() {
    print_info "Listing users..."
    response=$(http_get "/identity/users")
    print_json "$response"
}

molnos_user_create() {
    local email="$1"
    local name="$2"
    local roles="${3:-user}"

    if [ -z "$email" ] || [ -z "$name" ]; then
        print_error "Email and name are required"
        echo "Usage: molnos users create <email> <name> [roles]"
        exit 1
    fi

    print_info "Creating user $email..."
    response=$(http_post "/identity/users" "{\"email\":\"$email\",\"name\":\"$name\",\"roles\":[\"$roles\"]}")
    print_json "$response"
}

molnos_user_get() {
    local user_id="$1"

    if [ -z "$user_id" ]; then
        print_error "User ID is required"
        echo "Usage: molnos users get <user_id>"
        exit 1
    fi

    print_info "Getting user $user_id..."
    response=$(http_get "/identity/users/$user_id")
    print_json "$response"
}

molnos_user_update() {
    local user_id="$1"
    local data="$2"

    if [ -z "$user_id" ] || [ -z "$data" ]; then
        print_error "User ID and JSON data are required"
        echo "Usage: molnos users update <user_id> '<json_data>'"
        exit 1
    fi

    print_info "Updating user $user_id..."
    response=$(http_patch "/identity/users/$user_id" "$data")
    print_json "$response"
}

molnos_user_delete() {
    local user_id="$1"

    if [ -z "$user_id" ]; then
        print_error "User ID is required"
        echo "Usage: molnos users delete <user_id>"
        exit 1
    fi

    if [ "$FORCE_FLAG" != "true" ]; then
        if ! confirm "Delete user $user_id? This action cannot be undone."; then
            print_info "Deletion cancelled."
            exit 0
        fi
    fi

    print_info "Deleting user $user_id..."
    response=$(http_delete "/identity/users/$user_id")
    print_json "$response"
}

molnos_service_accounts_list() {
    print_info "Listing service accounts..."
    response=$(http_get "/identity/service-accounts")
    print_json "$response"
}

molnos_service_account_create() {
    local name="$1"
    local description="$2"
    local roles="$3"

    if [ -z "$name" ] || [ -z "$description" ] || [ -z "$roles" ]; then
        print_error "Name, description, and roles are required"
        echo "Usage: molnos service-accounts create <name> <description> <roles>"
        exit 1
    fi

    print_info "Creating service account $name..."
    response=$(http_post "/identity/service-accounts" "{\"name\":\"$name\",\"description\":\"$description\",\"roles\":[\"$roles\"]}")
    print_json "$response"
    print_info "Save the API key shown above - it will not be shown again!"
}

molnos_service_account_get() {
    local sa_id="$1"

    if [ -z "$sa_id" ]; then
        print_error "Service account ID is required"
        echo "Usage: molnos service-accounts get <service_account_id>"
        exit 1
    fi

    print_info "Getting service account $sa_id..."
    response=$(http_get "/identity/service-accounts/$sa_id")
    print_json "$response"
}

molnos_service_account_update() {
    local sa_id="$1"
    local data="$2"

    if [ -z "$sa_id" ] || [ -z "$data" ]; then
        print_error "Service account ID and JSON data are required"
        echo "Usage: molnos service-accounts update <sa_id> '<json_data>'"
        exit 1
    fi

    print_info "Updating service account $sa_id..."
    response=$(http_patch "/identity/service-accounts/$sa_id" "$data")
    print_json "$response"
}

molnos_service_account_delete() {
    local sa_id="$1"

    if [ -z "$sa_id" ]; then
        print_error "Service account ID is required"
        echo "Usage: molnos service-accounts delete <sa_id>"
        exit 1
    fi

    if [ "$FORCE_FLAG" != "true" ]; then
        if ! confirm "Delete service account $sa_id and revoke its API key? This action cannot be undone."; then
            print_info "Deletion cancelled."
            exit 0
        fi
    fi

    print_info "Deleting service account $sa_id..."
    response=$(http_delete "/identity/service-accounts/$sa_id")
    print_json "$response"
}

molnos_service_account_rotate() {
    local sa_id="$1"

    if [ -z "$sa_id" ]; then
        print_error "Service account ID is required"
        echo "Usage: molnos service-accounts rotate-key <sa_id>"
        exit 1
    fi

    print_info "Rotating API key for service account $sa_id..."
    response=$(http_post "/identity/service-accounts/$sa_id/rotate-key" "")
    print_json "$response"
    print_info "Save the new API key shown above - it will not be shown again!"
}

molnos_roles_list() {
    print_info "Listing roles..."
    response=$(http_get "/identity/roles")
    print_json "$response"
}

molnos_role_get() {
    local role_id="$1"

    if [ -z "$role_id" ]; then
        print_error "Role ID is required"
        echo "Usage: molnos roles get <role_id>"
        exit 1
    fi

    print_info "Getting role $role_id..."
    response=$(http_get "/identity/roles/$role_id")
    print_json "$response"
}

molnos_role_create() {
    local data="$1"

    if [ -z "$data" ]; then
        print_error "JSON data is required"
        echo "Usage: molnos roles create '<json_data>'"
        exit 1
    fi

    print_info "Creating role..."
    response=$(http_post "/identity/roles" "$data")
    print_json "$response"
}

molnos_role_update() {
    local role_id="$1"
    local data="$2"

    if [ -z "$role_id" ] || [ -z "$data" ]; then
        print_error "Role ID and JSON data are required"
        echo "Usage: molnos roles update <role_id> '<json_data>'"
        exit 1
    fi

    print_info "Updating role $role_id..."
    response=$(http_patch "/identity/roles/$role_id" "$data")
    print_json "$response"
}

molnos_role_delete() {
    local role_id="$1"

    if [ -z "$role_id" ]; then
        print_error "Role ID is required"
        echo "Usage: molnos roles delete <role_id>"
        exit 1
    fi

    if [ "$FORCE_FLAG" != "true" ]; then
        if ! confirm "Delete role $role_id? This action cannot be undone."; then
            print_info "Deletion cancelled."
            exit 0
        fi
    fi

    print_info "Deleting role $role_id..."
    response=$(http_delete "/identity/roles/$role_id")
    print_json "$response"
}

# ============================================================================
# Service Management Commands
# ============================================================================

molnos_services_list() {
    print_info "Listing services..."
    response=$(http_get "/management/services")
    print_json "$response"
}

molnos_service_register() {
    local data="$1"

    if [ -z "$data" ]; then
        print_error "JSON data is required"
        echo "Usage: molnos services register '<json_data>'"
        exit 1
    fi

    print_info "Registering service..."
    response=$(http_post "/management/service" "$data")
    print_json "$response"
}

molnos_service_get() {
    local service_name="$1"

    if [ -z "$service_name" ]; then
        print_error "Service name is required"
        echo "Usage: molnos services get <service_name>"
        exit 1
    fi

    print_info "Getting service $service_name..."
    response=$(http_get "/management/service/$service_name")
    print_json "$response"
}

molnos_service_update() {
    local service_name="$1"
    local data="$2"

    if [ -z "$service_name" ] || [ -z "$data" ]; then
        print_error "Service name and JSON data are required"
        echo "Usage: molnos services update <service_name> '<json_data>'"
        exit 1
    fi

    print_info "Updating service $service_name..."
    response=$(http_put "/management/service/$service_name" "$data")
    print_json "$response"
}

molnos_service_remove() {
    local service_name="$1"

    if [ -z "$service_name" ]; then
        print_error "Service name is required"
        echo "Usage: molnos services remove <service_name>"
        exit 1
    fi

    if [ "$FORCE_FLAG" != "true" ]; then
        if ! confirm "Remove service $service_name? The service will be stopped and unregistered."; then
            print_info "Removal cancelled."
            exit 0
        fi
    fi

    print_info "Removing service $service_name..."
    response=$(http_delete "/management/service/$service_name")
    print_json "$response"
}

molnos_service_start_cmd() {
    local service_name="$1"

    if [ -z "$service_name" ]; then
        print_error "Service name is required"
        echo "Usage: molnos services start <service_name>"
        exit 1
    fi

    print_info "Starting service $service_name..."
    response=$(http_get "/management/service/$service_name/start")
    print_json "$response"
}

molnos_service_stop() {
    local service_name="$1"

    if [ -z "$service_name" ]; then
        print_error "Service name is required"
        echo "Usage: molnos services stop <service_name>"
        exit 1
    fi

    print_info "Stopping service $service_name..."
    response=$(http_get "/management/service/$service_name/stop")
    print_json "$response"
}

molnos_service_restart() {
    local service_name="$1"

    if [ -z "$service_name" ]; then
        print_error "Service name is required"
        echo "Usage: molnos services restart <service_name>"
        exit 1
    fi

    print_info "Restarting service $service_name..."
    response=$(http_get "/management/service/$service_name/restart")
    print_json "$response"
}

molnos_service_logs() {
    local service_name="$1"
    local limit="${2:-100}"
    local offset="${3:-0}"

    if [ -z "$service_name" ]; then
        print_error "Service name is required"
        echo "Usage: molnos services logs <service_name> [limit] [offset]"
        exit 1
    fi

    print_info "Getting logs for service $service_name..."
    response=$(http_get "/management/service/$service_name/logs?limit=$limit&offset=$offset")
    print_json "$response"
}

# ============================================================================
# Database Commands
# ============================================================================

molnos_db_tables_list() {
    print_info "Listing database tables..."
    response=$(http_get "/databases/tables")
    print_json "$response"
}

molnos_db_table_get() {
    local table_name="$1"

    if [ -z "$table_name" ]; then
        print_error "Table name is required"
        echo "Usage: molnos db table get <table_name>"
        exit 1
    fi

    print_info "Getting table $table_name..."
    response=$(http_get "/databases/tables/$table_name")
    print_json "$response"
}

molnos_db_table_size() {
    local table_name="$1"

    if [ -z "$table_name" ]; then
        print_error "Table name is required"
        echo "Usage: molnos db table size <table_name>"
        exit 1
    fi

    print_info "Getting size of table $table_name..."
    response=$(http_get "/databases/table?tableName=$table_name")
    print_json "$response"
}

molnos_db_table_create() {
    local table_name="$1"
    local context="$2"

    if [ -z "$table_name" ]; then
        print_error "Table name is required"
        echo "Usage: molnos db table create <table_name> [--context=<name>]"
        exit 1
    fi

    # Check if table_name is actually a flag (user passed --context first)
    if [[ "$table_name" == --* ]]; then
        print_error "Table name is required"
        echo "Usage: molnos db table create <table_name> [--context=<name>]"
        exit 1
    fi

    # Parse context from second arg if it's a flag
    if [[ "$context" == --context=* ]]; then
        context="${context#*=}"
    fi

    local payload=""
    if [ -n "$context" ]; then
        payload="{\"context\":\"$context\"}"
    fi

    print_info "Creating table $table_name..."
    response=$(http_post "/databases/tables/$table_name" "$payload")
    print_json "$response"
}

molnos_db_table_delete() {
    local table_name="$1"

    if [ -z "$table_name" ]; then
        print_error "Table name is required"
        echo "Usage: molnos db table delete <table_name>"
        exit 1
    fi

    if [ "$FORCE_FLAG" != "true" ]; then
        if ! confirm "Delete table $table_name and all its data? This action cannot be undone."; then
            print_info "Deletion cancelled."
            exit 0
        fi
    fi

    print_info "Deleting table $table_name..."
    response=$(http_delete "/databases/tables/$table_name")
    print_json "$response"
}

molnos_db_table_items() {
    local table_name="$1"

    if [ -z "$table_name" ]; then
        print_error "Table name is required"
        echo "Usage: molnos db table items <table_name>"
        exit 1
    fi

    print_info "Getting items from table $table_name..."
    response=$(http_get "/databases/tables/$table_name/items")
    print_json "$response"
}

molnos_db_get() {
    local table_name="$1"
    local key="$2"

    if [ -z "$table_name" ] || [ -z "$key" ]; then
        print_error "Table name and key are required"
        echo "Usage: molnos db get <table_name> <key>"
        exit 1
    fi

    print_info "Getting value from ${table_name}[${key}]..."
    response=$(http_post "/databases/get" "{\"tableName\":\"$table_name\",\"key\":\"$key\"}")
    print_json "$response"
}

molnos_db_write() {
    local table_name="$1"
    local key="$2"
    local value="$3"

    if [ -z "$table_name" ] || [ -z "$key" ] || [ -z "$value" ]; then
        print_error "Table name, key, and value are required"
        echo "Usage: molnos db write <table_name> <key> '<json_value>'"
        exit 1
    fi

    print_info "Writing to ${table_name}[${key}]..."
    response=$(http_post "/databases/write" "{\"tableName\":\"$table_name\",\"key\":\"$key\",\"value\":$value}")
    print_json "$response"
}

molnos_db_delete() {
    local table_name="$1"
    local key="$2"

    if [ -z "$table_name" ] || [ -z "$key" ]; then
        print_error "Table name and key are required"
        echo "Usage: molnos db delete <table_name> <key>"
        exit 1
    fi

    print_info "Deleting from ${table_name}[${key}]..."
    response=$(http_delete "/databases/delete?tableName=$table_name&key=$key")
    print_json "$response"
}

# ============================================================================
# Functions Commands
# ============================================================================

molnos_functions_list() {
    print_info "Listing functions..."
    response=$(http_get "/functions/list")
    print_json "$response"
}

molnos_function_deploy() {
    local name="$1"
    local code_file="$2"
    shift 2  # Remove first two arguments

    # Parse optional flags
    local methods=""
    local pass_all_headers=""
    local allow_unauthenticated=""
    local bindings=""
    local triggers=""
    local context=""

    while [[ $# -gt 0 ]]; do
        case "$1" in
            --methods=*)
                methods="${1#*=}"
                shift
                ;;
            --pass-all-headers)
                pass_all_headers="true"
                shift
                ;;
            --allow-unauthenticated)
                allow_unauthenticated="true"
                shift
                ;;
            --bindings=*)
                bindings="${1#*=}"
                shift
                ;;
            --triggers=*)
                triggers="${1#*=}"
                shift
                ;;
            --context=*)
                context="${1#*=}"
                shift
                ;;
            *)
                print_error "Unknown option: $1"
                echo "Usage: molnos functions deploy <name> <code_file> --triggers='<json>' [--methods=GET,POST] [--pass-all-headers] [--allow-unauthenticated] [--bindings='<json>'] [--context=<name>]"
                exit 1
                ;;
        esac
    done

    if [ -z "$name" ] || [ -z "$code_file" ]; then
        print_error "Function name and code file are required"
        echo "Usage: molnos functions deploy <name> <code_file> --triggers='<json>' [--methods=GET,POST] [--pass-all-headers] [--allow-unauthenticated] [--bindings='<json>'] [--context=<name>]"
        exit 1
    fi

    if [ -z "$triggers" ]; then
        print_error "Triggers are required. Specify at least one trigger (e.g. --triggers='[{\"type\":\"http\"}]')"
        echo "Usage: molnos functions deploy <name> <code_file> --triggers='<json>' [--methods=GET,POST] [--pass-all-headers] [--allow-unauthenticated] [--bindings='<json>'] [--context=<name>]"
        exit 1
    fi

    if [ ! -f "$code_file" ]; then
        print_error "Code file not found: $code_file"
        exit 1
    fi

    print_info "Deploying function $name..."
    code=$(cat "$code_file" | node -e "console.log(JSON.stringify(require('fs').readFileSync(0,'utf8')))")

    # Build JSON payload (triggers is required)
    local payload="{\"name\":\"$name\",\"code\":$code,\"triggers\":$triggers"

    # Add optional fields
    if [ -n "$methods" ]; then
        # Convert comma-separated string to JSON array
        local methods_array=$(echo "$methods" | node -e "console.log(JSON.stringify(require('fs').readFileSync(0,'utf8').trim().split(',')))")
        payload="$payload,\"methods\":$methods_array"
    fi

    if [ "$pass_all_headers" = "true" ]; then
        payload="$payload,\"passAllHeaders\":true"
    fi

    if [ "$allow_unauthenticated" = "true" ]; then
        payload="$payload,\"allowUnauthenticated\":true"
    fi

    if [ -n "$bindings" ]; then
        payload="$payload,\"bindings\":$bindings"
    fi

    if [ -n "$context" ]; then
        payload="$payload,\"context\":\"$context\""
    fi

    payload="$payload}"

    response=$(http_post "/functions/deploy" "$payload")
    print_json "$response"
}

molnos_function_get() {
    local function_id="$1"

    if [ -z "$function_id" ]; then
        print_error "Function ID is required"
        echo "Usage: molnos functions get <function_id>"
        exit 1
    fi

    print_info "Getting function $function_id..."
    response=$(http_get "/functions/$function_id")
    print_json "$response"
}

molnos_function_config() {
    local function_id="$1"

    if [ -z "$function_id" ]; then
        print_error "Function ID is required"
        echo "Usage: molnos functions config <function_id>"
        exit 1
    fi

    print_info "Getting function config $function_id..."
    response=$(http_get "/functions/$function_id/config")
    print_json "$response"
}

molnos_function_update() {
    local function_id="$1"
    local code_file="$2"
    shift 2  # Remove first two arguments

    # Parse optional flags
    local methods=""
    local pass_all_headers=""
    local allow_unauthenticated=""
    local bindings=""
    local triggers=""
    local update_code=false

    # Check if code_file is actually a file or a flag
    if [ -n "$code_file" ] && [ -f "$code_file" ]; then
        update_code=true
    elif [ -n "$code_file" ] && [[ "$code_file" == --* ]]; then
        # It's a flag, put it back for processing
        set -- "$code_file" "$@"
        code_file=""
    fi

    while [[ $# -gt 0 ]]; do
        case "$1" in
            --methods=*)
                methods="${1#*=}"
                shift
                ;;
            --pass-all-headers)
                pass_all_headers="true"
                shift
                ;;
            --allow-unauthenticated)
                allow_unauthenticated="true"
                shift
                ;;
            --bindings=*)
                bindings="${1#*=}"
                shift
                ;;
            --triggers=*)
                triggers="${1#*=}"
                shift
                ;;
            *)
                print_error "Unknown option: $1"
                echo "Usage: molnos functions update <function_id> [code_file] [--methods=GET,POST] [--pass-all-headers] [--allow-unauthenticated] [--bindings='<json>'] [--triggers='<json>']"
                exit 1
                ;;
        esac
    done

    if [ -z "$function_id" ]; then
        print_error "Function ID is required"
        echo "Usage: molnos functions update <function_id> [code_file] [--methods=GET,POST] [--pass-all-headers] [--allow-unauthenticated] [--bindings='<json>'] [--triggers='<json>']"
        exit 1
    fi

    # Build JSON payload
    local payload="{"
    local has_field=false

    # Add code if provided
    if [ "$update_code" = true ]; then
        code=$(cat "$code_file" | node -e "console.log(JSON.stringify(require('fs').readFileSync(0,'utf8')))")
        payload="$payload\"code\":$code"
        has_field=true
    fi

    # Add optional fields
    if [ -n "$methods" ]; then
        [ "$has_field" = true ] && payload="$payload,"
        local methods_array=$(echo "$methods" | node -e "console.log(JSON.stringify(require('fs').readFileSync(0,'utf8').trim().split(',')))")
        payload="$payload\"methods\":$methods_array"
        has_field=true
    fi

    if [ "$pass_all_headers" = "true" ]; then
        [ "$has_field" = true ] && payload="$payload,"
        payload="$payload\"passAllHeaders\":true"
        has_field=true
    fi

    if [ "$allow_unauthenticated" = "true" ]; then
        [ "$has_field" = true ] && payload="$payload,"
        payload="$payload\"allowUnauthenticated\":true"
        has_field=true
    fi

    if [ -n "$bindings" ]; then
        [ "$has_field" = true ] && payload="$payload,"
        payload="$payload\"bindings\":$bindings"
        has_field=true
    fi

    if [ -n "$triggers" ]; then
        [ "$has_field" = true ] && payload="$payload,"
        payload="$payload\"triggers\":$triggers"
        has_field=true
    fi

    payload="$payload}"

    if [ "$has_field" = false ]; then
        print_error "At least one update field is required (code file or flags)"
        echo "Usage: molnos functions update <function_id> [code_file] [--methods=GET,POST] [--pass-all-headers] [--allow-unauthenticated] [--bindings='<json>'] [--triggers='<json>']"
        exit 1
    fi

    print_info "Updating function $function_id..."
    response=$(http_put "/functions/$function_id" "$payload")
    print_json "$response"
}

molnos_function_delete() {
    local function_id="$1"

    if [ -z "$function_id" ]; then
        print_error "Function ID is required"
        echo "Usage: molnos functions delete <function_id>"
        exit 1
    fi

    if [ "$FORCE_FLAG" != "true" ]; then
        if ! confirm "Delete function $function_id? This action cannot be undone."; then
            print_info "Deletion cancelled."
            exit 0
        fi
    fi

    print_info "Deleting function $function_id..."
    response=$(http_delete "/functions/$function_id")
    print_json "$response"
}

molnos_function_invoke() {
    local function_id="$1"
    local method="${2:-GET}"
    local data="${3:-}"

    if [ -z "$function_id" ]; then
        print_error "Function ID is required"
        echo "Usage: molnos functions invoke <function_id> [method] [data]"
        exit 1
    fi

    print_info "Invoking function $function_id with $method..."

    if [ "$method" = "GET" ]; then
        response=$(http_get "/functions/run/$function_id")
    else
        response=$(http_post "/functions/run/$function_id" "$data")
    fi

    print_json "$response"
}

molnos_function_stats() {
    print_info "Getting function statistics..."
    response=$(http_get "/functions/stats")
    print_json "$response"
}

# ============================================================================
# Storage Commands
# ============================================================================

molnos_storage_buckets_list() {
    print_info "Listing buckets..."
    response=$(http_get "/storage/buckets")
    print_json "$response"
}

molnos_storage_bucket_create() {
    local bucket="$1"
    shift

    local public=""
    local context=""

    # Parse optional flags
    while [[ $# -gt 0 ]]; do
        case "$1" in
            --public)
                public="true"
                shift
                ;;
            --context=*)
                context="${1#*=}"
                shift
                ;;
            *)
                print_error "Unknown option: $1"
                echo "Usage: molnos storage bucket create <bucket> [--public] [--context=<name>]"
                exit 1
                ;;
        esac
    done

    if [ -z "$bucket" ]; then
        print_error "Bucket name is required"
        echo "Usage: molnos storage bucket create <bucket> [--public] [--context=<name>]"
        exit 1
    fi

    # Build JSON payload
    local payload=""
    local has_field=""

    if [ "$public" = "true" ]; then
        payload="{\"public\":true"
        has_field="true"
    fi

    if [ -n "$context" ]; then
        if [ -n "$has_field" ]; then
            payload="$payload,\"context\":\"$context\""
        else
            payload="{\"context\":\"$context\""
            has_field="true"
        fi
    fi

    if [ -n "$has_field" ]; then
        payload="$payload}"
    fi

    print_info "Creating bucket $bucket..."
    response=$(http_post "/storage/buckets/$bucket" "$payload")
    print_json "$response"
}

molnos_storage_bucket_get() {
    local bucket="$1"

    if [ -z "$bucket" ]; then
        print_error "Bucket name is required"
        echo "Usage: molnos storage bucket get <bucket>"
        exit 1
    fi

    print_info "Getting bucket stats for $bucket..."
    response=$(http_get "/storage/buckets/$bucket")
    print_json "$response"
}

molnos_storage_bucket_update() {
    local bucket="$1"
    shift
    local settings="$*"

    if [ -z "$bucket" ]; then
        print_error "Bucket name is required"
        echo "Usage: molnos storage bucket update <bucket> <setting>"
        echo ""
        echo "Settings:"
        echo "  public              Make bucket public"
        echo "  public=true         Make bucket public"
        echo "  public=false        Make bucket private"
        echo "  private             Make bucket private"
        exit 1
    fi

    if [ -z "$settings" ]; then
        print_error "At least one setting is required"
        echo "Usage: molnos storage bucket update <bucket> <setting>"
        echo ""
        echo "Settings:"
        echo "  public              Make bucket public"
        echo "  public=true         Make bucket public"
        echo "  public=false        Make bucket private"
        echo "  private             Make bucket private"
        exit 1
    fi

    # Build JSON from settings
    local json_data=""
    local public_value=""

    for setting in $settings; do
        case "$setting" in
            public|public=true)
                public_value="true"
                ;;
            private|public=false)
                public_value="false"
                ;;
            *)
                print_error "Unknown setting: $setting"
                echo "Valid settings: public, public=true, public=false, private"
                exit 1
                ;;
        esac
    done

    # Construct JSON
    if [ -n "$public_value" ]; then
        json_data="{\"public\":$public_value}"
    fi

    if [ -z "$json_data" ]; then
        print_error "No valid settings provided"
        exit 1
    fi

    print_info "Updating bucket $bucket..."
    response=$(http_patch "/storage/buckets/$bucket" "$json_data")
    print_json "$response"
}

molnos_storage_bucket_delete() {
    local bucket="$1"

    if [ -z "$bucket" ]; then
        print_error "Bucket name is required"
        echo "Usage: molnos storage bucket delete <bucket>"
        exit 1
    fi

    if [ "$FORCE_FLAG" != "true" ]; then
        if ! confirm "Delete bucket $bucket and all its objects? This action cannot be undone."; then
            print_info "Deletion cancelled."
            exit 0
        fi
    fi

    print_info "Deleting bucket $bucket..."
    response=$(http_delete "/storage/buckets/$bucket")
    print_json "$response"
}

molnos_storage_objects_list() {
    local bucket="$1"
    local prefix="${2:-}"

    if [ -z "$bucket" ]; then
        print_error "Bucket name is required"
        echo "Usage: molnos storage objects list <bucket> [prefix]"
        exit 1
    fi

    print_info "Listing objects in bucket $bucket..."
    if [ -n "$prefix" ]; then
        response=$(http_get "/storage/buckets/$bucket/objects?prefix=$prefix")
    else
        response=$(http_get "/storage/buckets/$bucket/objects")
    fi
    print_json "$response"
}

molnos_storage_object_put() {
    local bucket="$1"
    local key="$2"
    local content="$3"

    if [ -z "$bucket" ] || [ -z "$key" ] || [ -z "$content" ]; then
        print_error "Bucket, key, and content are required"
        echo "Usage: molnos storage object put <bucket> <key> <content>"
        exit 1
    fi

    print_info "Uploading object to $bucket/$key..."
    response=$(http_put "/storage/buckets/$bucket/objects" "{\"key\":\"$key\",\"content\":\"$content\"}")
    print_json "$response"
}

molnos_storage_object_upload() {
    local bucket="$1"
    local key="$2"
    local file_path="$3"

    if [ -z "$bucket" ] || [ -z "$key" ] || [ -z "$file_path" ]; then
        print_error "Bucket, key, and file path are required"
        echo "Usage: molnos storage object upload <bucket> <key> <file_path>"
        exit 1
    fi

    if [ ! -f "$file_path" ]; then
        print_error "File not found: $file_path"
        exit 1
    fi

    print_info "Uploading file $file_path to $bucket/$key..."

    # Check if curl is available (required for multipart upload)
    if ! command -v curl &> /dev/null; then
        print_error "curl is required for file uploads"
        exit 1
    fi

    local token=$(get_token)

    if [ -n "$token" ]; then
        # Use multipart/form-data upload
        response=$(curl -sSL -X PUT \
            -H "Authorization: Bearer $token" \
            -F "key=$key" \
            -F "file=@$file_path" \
            "$API_URL/storage/buckets/$bucket/objects")
    else
        # No auth
        response=$(curl -sSL -X PUT \
            -F "key=$key" \
            -F "file=@$file_path" \
            "$API_URL/storage/buckets/$bucket/objects")
    fi

    print_json "$response"
}

molnos_storage_object_get() {
    local bucket="$1"
    local key="$2"

    if [ -z "$bucket" ] || [ -z "$key" ]; then
        print_error "Bucket and key are required"
        echo "Usage: molnos storage object get <bucket> <key>"
        exit 1
    fi

    print_info "Getting object from $bucket/$key..."
    response=$(http_post "/storage/buckets/$bucket/objects" "{\"key\":\"$key\"}")
    print_json "$response"
}

molnos_storage_object_delete() {
    local bucket="$1"
    local key="$2"

    if [ -z "$bucket" ] || [ -z "$key" ]; then
        print_error "Bucket and key are required"
        echo "Usage: molnos storage object delete <bucket> <key>"
        exit 1
    fi

    print_info "Deleting object from $bucket/$key..."
    response=$(http_delete "/storage/buckets/$bucket/objects" "{\"key\":\"$key\"}")
    print_json "$response"
}

molnos_storage_object_sign() {
    local bucket="$1"
    local key="$2"
    local expires_in="$3"

    if [ -z "$bucket" ] || [ -z "$key" ]; then
        print_error "Bucket and key are required"
        echo ""
        echo "Usage: molnos storage object sign <bucket> <key> [expires-in-seconds]"
        echo ""
        echo "Examples:"
        echo "  molnos storage object sign my-bucket file.pdf"
        echo "  molnos storage object sign my-bucket file.pdf 3600  # 1 hour"
        echo "  molnos storage object sign my-bucket file.pdf 86400 # 24 hours"
        exit 1
    fi

    print_info "Generating signed URL for $bucket/$key..."

    local query_string=""
    if [ -n "$expires_in" ]; then
        query_string="?expiresIn=$expires_in"
    fi

    response=$(http_post "/storage/buckets/$bucket/objects/$key/sign$query_string" "{}")
    print_json "$response"

    # Extract and display the signed URL prominently
    local signed_url
    signed_url=$(echo "$response" | grep -o '"url":"[^"]*"' | sed 's/"url":"\([^"]*\)"/\1/')
    if [ -n "$signed_url" ]; then
        echo ""
        print_success "Signed URL:"
        echo "$signed_url"
    fi
}

# ============================================================================
# Sites Commands
# ============================================================================

molnos_sites_list() {
    print_info "Listing static sites..."
    response=$(http_get "/sites/projects")
    print_json "$response"
}

molnos_site_deploy() {
    local files_json=""
    local project_id=""
    local context=""

    # Parse arguments
    while [[ $# -gt 0 ]]; do
        case "$1" in
            --project-id=*)
                project_id="${1#*=}"
                shift
                ;;
            -p)
                project_id="$2"
                shift 2
                ;;
            --context=*)
                context="${1#*=}"
                shift
                ;;
            *)
                files_json="$1"
                shift
                ;;
        esac
    done

    if [ -z "$files_json" ]; then
        print_error "Files JSON is required"
        echo "Usage: molnos sites deploy '<files_json>' [--project-id=<id>] [--context=<name>]"
        echo "       molnos sites deploy -                  (read from stdin)"
        echo "       molnos sites deploy - --project-id=<id> --context=<name>"
        echo ""
        echo "Project ID format: lowercase letters, numbers, hyphens (4-40 chars)"
        exit 1
    fi

    # Validate project ID format if provided
    if [ -n "$project_id" ]; then
        if ! [[ "$project_id" =~ ^[a-z0-9-]{4,40}$ ]]; then
            print_error "Invalid project ID format: $project_id"
            echo "Project ID must be 4-40 characters and contain only lowercase letters, numbers, and hyphens"
            exit 1
        fi
    fi

    # If files_json is "-", read from stdin
    if [ "$files_json" = "-" ]; then
        files_json=$(cat)
    fi

    # Inject context into the JSON payload if provided
    if [ -n "$context" ]; then
        # Use node to safely add context to JSON
        files_json=$(echo "$files_json" | node -e "
            const chunks = [];
            process.stdin.on('data', chunk => chunks.push(chunk));
            process.stdin.on('end', () => {
                const json = JSON.parse(chunks.join(''));
                json.context = '$context';
                console.log(JSON.stringify(json));
            });
        ")
    fi

    print_info "Deploying site ${project_id:-auto-generated}..."
    response=$(http_post "/sites/projects" "$files_json")
    print_json "$response"
}

molnos_site_download() {
    local project_id="$1"

    if [ -z "$project_id" ]; then
        print_error "Project ID is required"
        echo "Usage: molnos sites download <project_id>"
        echo ""
        echo "Project ID format: lowercase letters, numbers, hyphens (4-40 chars)"
        exit 1
    fi

    # Validate project ID format
    if ! [[ "$project_id" =~ ^[a-z0-9-]{4,40}$ ]]; then
        print_error "Invalid project ID format: $project_id"
        echo "Project ID must be 4-40 characters and contain only lowercase letters, numbers, and hyphens"
        exit 1
    fi

    print_info "Downloading site $project_id..."
    response=$(http_get "/sites/projects/$project_id/download")
    print_json "$response"
}

molnos_site_delete() {
    local project_id="$1"

    if [ -z "$project_id" ]; then
        print_error "Project ID is required"
        echo "Usage: molnos sites delete <project_id>"
        echo ""
        echo "Project ID format: lowercase letters, numbers, hyphens (4-40 chars)"
        exit 1
    fi

    # Validate project ID format
    if ! [[ "$project_id" =~ ^[a-z0-9-]{4,40}$ ]]; then
        print_error "Invalid project ID format: $project_id"
        echo "Project ID must be 4-40 characters and contain only lowercase letters, numbers, and hyphens"
        exit 1
    fi

    if [ "$FORCE_FLAG" != "true" ]; then
        if ! confirm "Delete site $project_id? This action cannot be undone."; then
            print_info "Deletion cancelled."
            exit 0
        fi
    fi

    print_info "Deleting site $project_id..."
    response=$(http_delete "/sites/projects/$project_id")
    print_json "$response"
}

# ============================================================================
# Observability Commands
# ============================================================================

molnos_logs_query() {
    # Parse flags and build query parameters
    local query_params=""
    local raw_params=""

    while [[ $# -gt 0 ]]; do
        case "$1" in
            --service=*)
                local service="${1#*=}"
                [ -n "$query_params" ] && query_params="$query_params&"
                query_params="${query_params}service=$service"
                shift
                ;;
            --level=*)
                local level="${1#*=}"
                [ -n "$query_params" ] && query_params="$query_params&"
                query_params="${query_params}level=$level"
                shift
                ;;
            --search=*)
                local search="${1#*=}"
                [ -n "$query_params" ] && query_params="$query_params&"
                query_params="${query_params}search=$search"
                shift
                ;;
            --start-time=*)
                local start_time="${1#*=}"
                [ -n "$query_params" ] && query_params="$query_params&"
                query_params="${query_params}startTime=$start_time"
                shift
                ;;
            --end-time=*)
                local end_time="${1#*=}"
                [ -n "$query_params" ] && query_params="$query_params&"
                query_params="${query_params}endTime=$end_time"
                shift
                ;;
            --limit=*)
                local limit="${1#*=}"
                [ -n "$query_params" ] && query_params="$query_params&"
                query_params="${query_params}limit=$limit"
                shift
                ;;
            --offset=*)
                local offset="${1#*=}"
                [ -n "$query_params" ] && query_params="$query_params&"
                query_params="${query_params}offset=$offset"
                shift
                ;;
            *)
                # Treat as raw query parameter string (backwards compatibility)
                raw_params="$1"
                shift
                ;;
        esac
    done

    # Combine structured params with raw params
    if [ -n "$raw_params" ]; then
        if [ -n "$query_params" ]; then
            query_params="${query_params}&${raw_params}"
        else
            query_params="$raw_params"
        fi
    fi

    print_info "Querying logs..."
    if [ -n "$query_params" ]; then
        response=$(http_get "/observability/events?$query_params")
    else
        response=$(http_get "/observability/events")
    fi
    print_json "$response"
}

molnos_log_event() {
    local data="$1"

    if [ -z "$data" ]; then
        print_error "JSON data is required"
        echo "Usage: molnos logs event '<json_data>'"
        exit 1
    fi

    print_info "Logging event..."
    response=$(http_post "/observability/events" "$data")
    print_json "$response"
}

molnos_logs_stats() {
    print_info "Getting log statistics..."
    response=$(http_get "/observability/stats")
    print_json "$response"
}

molnos_logs_cleanup() {
    local days="$1"

    if [ -z "$days" ]; then
        print_error "Number of days is required"
        echo "Usage: molnos logs cleanup <days>"
        exit 1
    fi

    if [ "$FORCE_FLAG" != "true" ]; then
        if ! confirm "Delete all logs older than $days days? This action cannot be undone."; then
            print_info "Cleanup cancelled."
            exit 0
        fi
    fi

    print_info "Cleaning up logs older than $days days..."
    response=$(http_delete "/observability/events/cleanup" "{\"olderThanDays\":$days}")
    print_json "$response"
}

molnos_logs_flush() {
    print_info "Flushing log buffer..."
    response=$(http_post "/observability/flush" "")
    print_json "$response"
}

molnos_system_metrics() {
    print_info "Getting system metrics..."
    response=$(http_get "/observability/metrics/system")
    print_json "$response"
}

# ============================================================================
# Schemas Commands
# ============================================================================

molnos_schemas_list() {
    print_info "Listing schemas..."
    response=$(http_get "/schemas")
    print_json "$response"
}

molnos_schema_create() {
    local json="$1"

    if [ -z "$json" ]; then
        print_error "Schema JSON is required"
        echo "Usage: molnos schemas create '<json>'"
        echo ""
        echo "Example:"
        echo "  molnos schemas create '{\"name\":\"order-created\",\"description\":\"Emitted when order is placed\",\"schema\":{\"properties\":{\"orderId\":{\"type\":\"string\"},\"amount\":{\"type\":\"number\"}},\"required\":[\"orderId\",\"amount\"]}}'"
        exit 1
    fi

    print_info "Creating schema..."
    response=$(http_post "/schemas" "$json")
    print_json "$response"
}

molnos_schema_get() {
    local name="$1"

    if [ -z "$name" ]; then
        print_error "Schema name is required"
        echo "Usage: molnos schemas get <name>"
        exit 1
    fi

    print_info "Getting schema $name..."
    response=$(http_get "/schemas/$name")
    print_json "$response"
}

molnos_schema_update() {
    local name="$1"
    local json="$2"

    if [ -z "$name" ] || [ -z "$json" ]; then
        print_error "Schema name and JSON are required"
        echo "Usage: molnos schemas update <name> '<json>'"
        echo ""
        echo "Example:"
        echo "  molnos schemas update order-created '{\"schema\":{\"properties\":{\"orderId\":{\"type\":\"string\"}},\"required\":[\"orderId\"]}}'"
        exit 1
    fi

    print_info "Updating schema $name..."
    response=$(http_put "/schemas/$name" "$json")
    print_json "$response"
}

molnos_schema_delete() {
    local name="$1"

    if [ -z "$name" ]; then
        print_error "Schema name is required"
        echo "Usage: molnos schemas delete <name>"
        exit 1
    fi

    if [ "$FORCE_FLAG" != "true" ]; then
        if ! confirm "Delete schema $name? This action cannot be undone."; then
            print_info "Deletion cancelled."
            exit 0
        fi
    fi

    print_info "Deleting schema $name..."
    response=$(http_delete "/schemas/$name")
    print_json "$response"
}

molnos_schema_version() {
    local name="$1"
    local version="$2"

    if [ -z "$name" ] || [ -z "$version" ]; then
        print_error "Schema name and version are required"
        echo "Usage: molnos schemas version <name> <version>"
        echo ""
        echo "Example:"
        echo "  molnos schemas version order-created 1"
        exit 1
    fi

    print_info "Getting schema $name version $version..."
    response=$(http_get "/schemas/$name/$version")
    print_json "$response"
}

# ============================================================================
# Context Commands
# ============================================================================

molnos_contexts_list() {
    print_info "Listing contexts..."
    response=$(http_get "/contexts")
    print_json "$response"
}

molnos_context_create() {
    local name="$1"
    local intent="$2"
    local attributes="$3"

    if [ -z "$name" ]; then
        print_error "Context name is required"
        echo "Usage: molnos context create <name> [intent] [attributes_json]"
        exit 1
    fi

    local data="{\"name\":\"$name\""
    if [ -n "$intent" ]; then
        data="$data,\"intent\":\"$intent\""
    fi
    if [ -n "$attributes" ]; then
        data="$data,\"attributes\":$attributes"
    fi
    data="$data}"

    print_info "Creating context '$name'..."
    response=$(http_post "/contexts" "$data")
    print_json "$response"
}

molnos_context_get() {
    local name="$1"

    if [ -z "$name" ]; then
        print_error "Context name is required"
        echo "Usage: molnos context get <name>"
        exit 1
    fi

    print_info "Getting context '$name'..."
    response=$(http_get "/contexts/$name")
    print_json "$response"
}

molnos_context_update() {
    local name="$1"
    local data="$2"

    if [ -z "$name" ] || [ -z "$data" ]; then
        print_error "Context name and JSON data are required"
        echo "Usage: molnos context update <name> '<json_data>'"
        echo "Example: molnos context update billing '{\"intent\":\"Updated intent\"}'"
        exit 1
    fi

    print_info "Updating context '$name'..."
    response=$(http_patch "/contexts/$name" "$data")
    print_json "$response"
}

molnos_context_delete() {
    local name="$1"

    if [ -z "$name" ]; then
        print_error "Context name is required"
        echo "Usage: molnos context delete <name>"
        exit 1
    fi

    if [ "$FORCE_FLAG" != "true" ]; then
        if ! confirm "Delete context '$name'? Resources will NOT be deleted."; then
            print_info "Deletion cancelled."
            exit 0
        fi
    fi

    print_info "Deleting context '$name'..."
    response=$(http_delete "/contexts/$name")
    print_json "$response"
}

molnos_context_destroy() {
    local name="$1"

    if [ -z "$name" ]; then
        print_error "Context name is required"
        echo "Usage: molnos context destroy <name>"
        exit 1
    fi

    if [ "$FORCE_FLAG" != "true" ]; then
        echo ""
        print_error "WARNING: This will DELETE ALL RESOURCES in context '$name'!"
        echo "This includes: functions, databases, storage, sites, applications, users, and service accounts."
        echo ""
        if ! confirm "Are you absolutely sure you want to destroy context '$name' and all its resources?"; then
            print_info "Destruction cancelled."
            exit 0
        fi
    fi

    print_info "Destroying all resources in context '$name'..."
    response=$(http_delete "/contexts/$name/resources")
    print_json "$response"

    print_info "Deleting context '$name'..."
    response=$(http_delete "/contexts/$name")
    print_json "$response"

    print_success "Context '$name' and all its resources have been destroyed."
}

# ============================================================================
# AI Generation Commands
# ============================================================================

molnos_context_generate() {
    local name="$1"
    shift || true

    if [ -z "$name" ]; then
        print_error "Context name is required"
        echo "Usage: molnos context generate <name> [options]"
        echo ""
        echo "Options:"
        echo "  --intent <text>              Override or supplement the context intent"
        echo "  --resource-types <types>     Comma-separated: functions,sites"
        echo "  --feedback <text>            Feedback for refining a previous generation"
        echo "  --previous-attempt <id>      ID of previous generation to iterate on"
        echo "  --provider <provider>        Override AI provider (anthropic, openai, ollama, evroc)"
        echo "  --model <model>              Override AI model"
        echo "  --api-key <key>              User-provided API key for AI provider"
        exit 1
    fi

    local data="{"
    local has_field=false

    while [ $# -gt 0 ]; do
        case "$1" in
            --intent)
                [ "$has_field" = true ] && data="$data,"
                data="$data\"intent\":\"$2\""
                has_field=true
                shift 2
                ;;
            --resource-types)
                [ "$has_field" = true ] && data="$data,"
                # Convert comma-separated to JSON array
                local types_json="["
                IFS=',' read -ra TYPES <<< "$2"
                local first=true
                for t in "${TYPES[@]}"; do
                    [ "$first" = true ] && first=false || types_json="$types_json,"
                    types_json="$types_json\"$t\""
                done
                types_json="$types_json]"
                data="$data\"resourceTypes\":$types_json"
                has_field=true
                shift 2
                ;;
            --feedback)
                [ "$has_field" = true ] && data="$data,"
                data="$data\"iterationFeedback\":\"$2\""
                has_field=true
                shift 2
                ;;
            --previous-attempt)
                [ "$has_field" = true ] && data="$data,"
                data="$data\"previousAttemptId\":\"$2\""
                has_field=true
                shift 2
                ;;
            --provider)
                [ "$has_field" = true ] && data="$data,"
                data="$data\"providerOverride\":\"$2\""
                has_field=true
                shift 2
                ;;
            --model)
                [ "$has_field" = true ] && data="$data,"
                data="$data\"modelOverride\":\"$2\""
                has_field=true
                shift 2
                ;;
            --api-key)
                [ "$has_field" = true ] && data="$data,"
                data="$data\"userApiKey\":\"$2\""
                has_field=true
                shift 2
                ;;
            *)
                print_error "Unknown option: $1"
                exit 1
                ;;
        esac
    done

    data="$data}"

    print_info "Generating code for context '$name'..."
    response=$(http_post "/contexts/$name/generate" "$data")
    print_json "$response"
}

molnos_context_generations() {
    local name="$1"

    if [ -z "$name" ]; then
        print_error "Context name is required"
        echo "Usage: molnos context generations <name>"
        exit 1
    fi

    print_info "Listing generations for context '$name'..."
    response=$(http_get "/contexts/$name/generations")
    print_json "$response"
}

molnos_generation_get() {
    local id="$1"

    if [ -z "$id" ]; then
        print_error "Generation ID is required"
        echo "Usage: molnos generation get <id>"
        exit 1
    fi

    print_info "Getting generation '$id'..."
    response=$(http_get "/generations/$id")
    print_json "$response"
}

molnos_generation_delete() {
    local id="$1"

    if [ -z "$id" ]; then
        print_error "Generation ID is required"
        echo "Usage: molnos generation delete <id>"
        exit 1
    fi

    if [ "$FORCE_FLAG" != "true" ]; then
        if ! confirm "Delete generation '$id'?"; then
            print_info "Deletion cancelled."
            exit 0
        fi
    fi

    print_info "Deleting generation '$id'..."
    response=$(http_delete "/generations/$id")
    print_json "$response"
}

molnos_generation_apply() {
    local id="$1"

    if [ -z "$id" ]; then
        print_error "Generation ID is required"
        echo "Usage: molnos generation apply <id>"
        exit 1
    fi

    if [ "$FORCE_FLAG" != "true" ]; then
        if ! confirm "Apply generation '$id'? This will deploy the generated code and IAC configuration."; then
            print_info "Apply cancelled."
            exit 0
        fi
    fi

    print_info "Applying generation '$id'..."
    response=$(http_post "/generations/$id/apply" "{}")
    print_json "$response"
}

molnos_generation_discard() {
    local id="$1"

    if [ -z "$id" ]; then
        print_error "Generation ID is required"
        echo "Usage: molnos generation discard <id>"
        exit 1
    fi

    print_info "Discarding generation '$id'..."
    response=$(http_post "/generations/$id/discard" "{}")
    print_json "$response"
}

# ============================================================================
# IAC Commands
# ============================================================================

# Transform IAC config to inline file contents for functions and sites
# This reads source files locally and embeds them in the JSON for the API
transform_iac_config() {
    local file_path="$1"

    if ! command -v node &> /dev/null; then
        print_error "Node.js is required for IAC operations"
        exit 1
    fi

    node --input-type=module -e "
import { readFileSync, readdirSync, existsSync } from 'node:fs';
import { join, resolve, dirname } from 'node:path';

const filePath = process.argv[1];
const baseDir = dirname(resolve(filePath));
let config;

try {
    const input = readFileSync(filePath, 'utf8');
    config = JSON.parse(input);
} catch (e) {
    console.error('Failed to read/parse IAC config:', e.message);
    process.exit(1);
}

// Helper to read directory recursively and return files array
function readDirRecursive(dirPath, basePath = '') {
    const files = [];
    if (!existsSync(dirPath)) {
        console.error('Directory not found: ' + dirPath);
        process.exit(1);
    }

    const entries = readdirSync(dirPath, { withFileTypes: true });
    for (const entry of entries) {
        const fullPath = join(dirPath, entry.name);
        const relativePath = basePath ? join(basePath, entry.name) : entry.name;

        if (entry.isDirectory()) {
            files.push(...readDirRecursive(fullPath, relativePath));
        } else if (entry.isFile()) {
            const buffer = readFileSync(fullPath);
            files.push({
                path: relativePath,
                content: buffer.toString('base64'),
                encoding: 'base64'
            });
        }
    }
    return files;
}

// Transform functions: read source files and add as 'code'
if (config.resources?.functions) {
    for (const [name, fn] of Object.entries(config.resources.functions)) {
        if (fn.source) {
            const sourcePath = resolve(baseDir, fn.source);
            if (!existsSync(sourcePath)) {
                console.error('Function source file not found: ' + sourcePath);
                process.exit(1);
            }
            fn.code = readFileSync(sourcePath, 'utf8');
            delete fn.source;
        }
    }
}

// Transform sites: read source directories and add as 'files'
if (config.resources?.sites) {
    for (const [name, site] of Object.entries(config.resources.sites)) {
        if (site.source) {
            const sourcePath = resolve(baseDir, site.source);
            site.files = readDirRecursive(sourcePath);
            delete site.source;
        }
    }
}

console.log(JSON.stringify(config));
" "$file_path"
}

molnos_iac_validate() {
    local file="$1"

    if [ -z "$file" ]; then
        print_error "IAC configuration file is required"
        echo "Usage: molnos iac validate <file>"
        exit 1
    fi

    if [ ! -f "$file" ]; then
        print_error "File not found: $file"
        exit 1
    fi

    print_info "Validating IAC configuration from '$file'..."
    local tmp_file
    tmp_file=$(mktemp)
    transform_iac_config "$file" > "$tmp_file"

    local token
    token=$(get_token)
    response=$(curl -sSL -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $token" --data-binary "@$tmp_file" "$API_URL/iac/validate")
    rm -f "$tmp_file"
    print_json "$response"
}

molnos_iac_apply() {
    local file=""
    local prune=false

    # Parse arguments
    while [ $# -gt 0 ]; do
        case "$1" in
            --prune)
                prune=true
                shift
                ;;
            *)
                if [ -z "$file" ]; then
                    file="$1"
                fi
                shift
                ;;
        esac
    done

    if [ -z "$file" ]; then
        print_error "IAC configuration file is required"
        echo "Usage: molnos iac apply <file> [--prune]"
        exit 1
    fi

    if [ ! -f "$file" ]; then
        print_error "File not found: $file"
        exit 1
    fi

    local url="/iac/apply"
    if [ "$prune" = true ]; then
        url="/iac/apply?prune=true"
        print_info "Applying IAC configuration from '$file' with prune enabled..."
    else
        print_info "Applying IAC configuration from '$file'..."
    fi

    local tmp_file
    tmp_file=$(mktemp)
    transform_iac_config "$file" > "$tmp_file"

    local token
    token=$(get_token)
    response=$(curl -sSL -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $token" --data-binary "@$tmp_file" "$API_URL$url")
    rm -f "$tmp_file"
    print_json "$response"
}

molnos_iac_diff() {
    local file="$1"

    if [ -z "$file" ]; then
        print_error "IAC configuration file is required"
        echo "Usage: molnos iac diff <file>"
        exit 1
    fi

    if [ ! -f "$file" ]; then
        print_error "File not found: $file"
        exit 1
    fi

    print_info "Showing diff for IAC configuration from '$file'..."
    local tmp_file
    tmp_file=$(mktemp)
    transform_iac_config "$file" > "$tmp_file"

    local token
    token=$(get_token)
    response=$(curl -sSL -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $token" --data-binary "@$tmp_file" "$API_URL/iac/diff")
    rm -f "$tmp_file"
    print_json "$response"
}

# ============================================================================
# Documentation Commands
# ============================================================================

molnos_legal() {
    print_info "Opening MolnOS Software Agreement..."
    echo ""

    if command -v xdg-open &> /dev/null; then
        xdg-open "https://molnos.cloud/agreement.html"
    elif command -v open &> /dev/null; then
        open "https://molnos.cloud/agreement.html"
    elif command -v start &> /dev/null; then
        start "https://molnos.cloud/agreement.html"
    else
        print_info "Could not automatically open browser. Visit:"
        echo "https://molnos.cloud/agreement.html"
    fi

    echo ""
}

molnos_docs() {
    print_info "Opening MolnOS Documentation..."
    echo ""

    if command -v xdg-open &> /dev/null; then
        xdg-open "https://docs.molnos.cloud"
    elif command -v open &> /dev/null; then
        open "https://docs.molnos.cloud"
    elif command -v start &> /dev/null; then
        start "https://docs.molnos.cloud"
    else
        print_info "Could not automatically open browser. Visit:"
        echo "https://docs.molnos.cloud"
    fi

    echo ""
}

# ============================================================================
# Help
# ============================================================================

show_help() {
    echo "MolnOS CLI"
    echo "Version $VERSION"
    echo ""
    echo "Usage: molnos [--token <token>] [--force] <command> [subcommand] [options]"
    echo ""
    echo "Global Flags:"
    echo "  --token <token>                     Override authentication token for this command"
    echo "  --force, -f                         Skip confirmation prompts for destructive operations"
    echo "  --version, -v                       Show version information"
    echo ""
    echo "Authentication:"
    echo "  MolnOS supports multiple authentication methods (in priority order):"
    echo "    1. --token flag:                  molnos --token <token> <command>"
    echo "    2. MOLNOS_TOKEN env var:          export MOLNOS_TOKEN=<token>"
    echo "    3. Token file:                    ~/.molnos/token"
    echo "    4. MOLNOS_SERVICE_ACCOUNT_KEY:    export MOLNOS_SERVICE_ACCOUNT_KEY=<sa-key>"
    echo ""
    echo "  Run 'molnos auth configure' for interactive authentication setup"
    echo "  Run 'molnos auth status' to check current authentication status"
    echo ""
    echo "Server Management:"
    echo "  install                             Install MolnOS Core to ~/.molnos"
    echo "  upgrade [all|core|cli]              Upgrade to the latest version"
    echo "                                        all  - Both Core and CLI (default)"
    echo "                                        core - MolnOS Core only"
    echo "                                        cli  - CLI tool only"
    echo "  start                               Start the MolnOS Core server"
    echo "  uninstall                           Remove MolnOS from your system"
    echo "  init                                Create molnos.config.json template"
    echo ""
    echo "Health Status:"
    echo "  health                              Check API health status"
    echo ""
    echo "Service Commands:"
    echo "  auth                                Authentication commands"
    echo "  apps                                Application management"
    echo "  identities                          Identity management"
    echo "  users                               User management"
    echo "  service-accounts                    Service account management"
    echo "  roles                               Role management"
    echo "  services                            Service management"
    echo "  db                                  Database operations"
    echo "  functions                           Function management"
    echo "  storage                             Storage operations"
    echo "  sites                               Static site management"
    echo "  logs                                Logging and observability"
    echo "  schemas                             Event schema registry"
    echo ""
    echo "Infrastructure:"
    echo "  context                             Context management (resource grouping)"
    echo "  generation                          AI generation management"
    echo "  iac                                 Infrastructure-as-Code operations"
    echo ""
    echo "Configuration:"
    echo "  configure                           Configuration commands"
    echo "    configure url [URL]               Configure API URL"
    echo ""
    echo "Documentation:"
    echo "  legal                               Open software agreement"
    echo "  docs                                Open documentation"
    echo ""
    echo "Run 'molnos <command>' to see detailed subcommands for each command."
    echo ""
}

show_auth_help() {
    echo "Authentication Commands:"
    echo ""
    echo "  auth configure                    Interactive authentication setup"
    echo "  auth status                       Show current authentication status"
    echo "  auth login <email>                Request magic link via email"
    echo "  auth verify <token> <email>       Verify magic link and save token"
    echo "  auth refresh <refresh_token>      Refresh access token"
    echo "  auth logout                       Clear saved token"
    echo "  auth whoami                       Get current identity"
    echo ""
    echo "OAuth Commands:"
    echo "  auth oauth providers              List available OAuth providers"
    echo "  auth oauth initiate <provider> [redirect-uri]  Initiate OAuth flow"
    echo "  auth oauth callback <provider> <code> [state]  Process OAuth callback"
    echo ""
    echo "Authentication Methods (in priority order):"
    echo "  1. --token flag:                  molnos --token <token> <command>"
    echo "  2. MOLNOS_TOKEN env var:          export MOLNOS_TOKEN=<token>"
    echo "  3. Token file:                    ~/.molnos/token"
    echo "  4. MOLNOS_SERVICE_ACCOUNT_KEY:    export MOLNOS_SERVICE_ACCOUNT_KEY=<sa-key>"
    echo ""
}

show_apps_help() {
    echo "Application Management Commands:"
    echo ""
    echo "  apps list                         List all applications"
    echo "  apps create <name> <desc> <uri>... Create application with redirect URIs"
    echo "  apps get <id>                     Get application by ID"
    echo "  apps update <id> <json>           Update application"
    echo "  apps delete <id>                  Delete application"
    echo ""
    echo "Example:"
    echo "  molnos apps create \"My App\" \"My application\" https://example.com/callback"
    echo "  molnos apps update abc123 '{\"name\":\"Updated Name\"}'"
    echo ""
}

show_identities_help() {
    echo "Identity Management Commands:"
    echo ""
    echo "  identities list                   List all identities"
    echo ""
}

show_users_help() {
    echo "User Management Commands:"
    echo ""
    echo "  users list                        List all users"
    echo "  users create <email> <name> [role] Create user"
    echo "  users get <id>                    Get user by ID"
    echo "  users update <id> <json>          Update user"
    echo "  users delete <id>                 Delete user"
    echo ""
}

show_service_accounts_help() {
    echo "Service Account Management Commands:"
    echo ""
    echo "  service-accounts list             List service accounts"
    echo "  service-accounts create <name> <desc> <role>"
    echo "                                    Create service account"
    echo "  service-accounts get <id>         Get service account"
    echo "  service-accounts update <id> <json>"
    echo "                                    Update service account"
    echo "  service-accounts delete <id>      Delete service account"
    echo "  service-accounts rotate-key <id>  Rotate API key"
    echo ""
}

show_roles_help() {
    echo "Role Management Commands:"
    echo ""
    echo "  roles list                        List all roles"
    echo "  roles get <id>                    Get role by ID"
    echo "  roles create <json>               Create custom role"
    echo "  roles update <id> <json>          Update role"
    echo "  roles delete <id>                 Delete role"
    echo ""
}

show_services_help() {
    echo "Service Management Commands:"
    echo ""
    echo "  services list                     List all services"
    echo "  services register <json>          Register a service"
    echo "  services get <name>               Get service details"
    echo "  services update <name> <json>     Update service"
    echo "  services remove <name>            Remove service"
    echo "  services start <name>             Start service"
    echo "  services stop <name>              Stop service"
    echo "  services restart <name>           Restart service"
    echo "  services logs <name> [limit] [offset]"
    echo "                                    Get service logs"
    echo ""
}

show_db_help() {
    echo "Database Commands:"
    echo ""
    echo "  db tables                         List all tables"
    echo "  db table get <name>               Get table details"
    echo "  db table size <name>              Get table item count"
    echo "  db table create <name> [--context=<name>]"
    echo "                                    Create table"
    echo "  db table delete <name>            Delete table"
    echo "  db table items <name>             List items in table"
    echo "  db get <table> <key>              Get value"
    echo "  db write <table> <key> <json>     Write value"
    echo "  db delete <table> <key>           Delete value"
    echo ""
}

show_functions_help() {
    echo "Functions Commands:"
    echo ""
    echo "  functions list                    List all functions"
    echo "  functions deploy <name> <file> --triggers='<json>' [options]"
    echo "                                    Deploy function"
    echo "      Required:"
    echo "        --triggers='<json>'         Trigger configurations (http/event)"
    echo "                                    e.g. '[{\"type\":\"http\"}]'"
    echo "                                    e.g. '[{\"type\":\"event\",\"eventName\":\"order.created\"}]'"
    echo "      Options:"
    echo "        --methods=GET,POST          Restrict HTTP methods"
    echo "        --pass-all-headers          Pass all headers to function"
    echo "        --allow-unauthenticated     Allow unauthenticated execution"
    echo "        --bindings='<json>'         Service bindings configuration"
    echo "        --context=<name>            Associate with a context"
    echo "  functions get <id>                Get function details"
    echo "  functions config <id>             Get function config"
    echo "  functions update <id> [file] [options]"
    echo "                                    Update function (same options as deploy)"
    echo "  functions delete <id>             Delete function"
    echo "  functions invoke <id> [method] [data]"
    echo "                                    Invoke function"
    echo "  functions stats                   Get function statistics"
    echo ""
}

show_storage_help() {
    echo "Storage Commands:"
    echo ""
    echo "  storage buckets                   List all buckets"
    echo "  storage bucket create <name> [--public] [--context=<name>]"
    echo "                                    Create bucket"
    echo "  storage bucket get <name>         Get bucket stats"
    echo "  storage bucket update <name> <setting>"
    echo "                                    Update bucket settings:"
    echo "                                      public | public=true  - Make public"
    echo "                                      private | public=false - Make private"
    echo "  storage bucket delete <name>      Delete bucket"
    echo "  storage objects list <bucket> [prefix]"
    echo "                                    List objects in bucket"
    echo "  storage object put <bucket> <key> <content>"
    echo "                                    Upload text content"
    echo "  storage object upload <bucket> <key> <file_path>"
    echo "                                    Upload file (binary/text)"
    echo "  storage object get <bucket> <key>"
    echo "                                    Get object"
    echo "  storage object delete <bucket> <key>"
    echo "                                    Delete object"
    echo "  storage object sign <bucket> <key> [expires-in-seconds]"
    echo "                                    Generate signed URL for object"
    echo ""
}

show_sites_help() {
    echo "Static Sites Commands:"
    echo ""
    echo "  sites list                               List static sites"
    echo "  sites deploy <json> [--project-id=<id>] [--context=<name>]"
    echo "                                           Deploy site (use - for stdin)"
    echo "  sites download <id>                      Download site files"
    echo "  sites delete <id>                        Delete site"
    echo ""
    echo "Project ID Format:"
    echo "  - Must be 4-40 characters long"
    echo "  - Lowercase letters (a-z), numbers (0-9), and hyphens (-) only"
    echo "  - Examples: my-site, blog-2024, portfolio-v2"
    echo ""
}

show_schemas_help() {
    echo "Schema Registry Commands:"
    echo ""
    echo "  schemas list                      List all schemas"
    echo "  schemas create <json>             Create a new schema"
    echo "  schemas get <name>                Get schema (latest version)"
    echo "  schemas update <name> <json>      Update schema (creates new version)"
    echo "  schemas delete <name>             Delete schema"
    echo "  schemas version <name> <version>  Get specific schema version"
    echo ""
    echo "Schema names must be kebab-case (e.g., order-created, user-signed-up)."
    echo ""
    echo "Examples:"
    echo "  molnos schemas list"
    echo "  molnos schemas create '{\"name\":\"order-created\",\"schema\":{\"properties\":{\"orderId\":{\"type\":\"string\"}},\"required\":[\"orderId\"]}}'"
    echo "  molnos schemas get order-created"
    echo "  molnos schemas update order-created '{\"schema\":{\"properties\":{\"orderId\":{\"type\":\"string\"},\"amount\":{\"type\":\"number\"}},\"required\":[\"orderId\",\"amount\"]}}'"
    echo "  molnos schemas version order-created 1"
    echo "  molnos schemas delete order-created"
    echo ""
}

show_logs_help() {
    echo "Logging and Observability Commands:"
    echo ""
    echo "  logs query [options]              Query logs"
    echo "      Options:"
    echo "        --service=<name>            Filter by service name"
    echo "        --level=<level>             Filter by level (info/warn/error/debug)"
    echo "        --search=<term>             Search in messages"
    echo "        --start-time=<timestamp>    Start time filter (milliseconds)"
    echo "        --end-time=<timestamp>      End time filter (milliseconds)"
    echo "        --limit=<n>                 Max results (default: 1000)"
    echo "        --offset=<n>                Pagination offset (default: 0)"
    echo "      Or use raw query string for backwards compatibility"
    echo "  logs event <json>                 Log event"
    echo "  logs stats                        Get log statistics"
    echo "  logs cleanup <days>               Clean up old logs"
    echo "  logs flush                        Flush log buffer"
    echo "  logs metrics                      Get system metrics"
    echo ""
}

show_configure_help() {
    echo "Configuration Commands:"
    echo ""
    echo "  configure url [URL]               Configure API URL"
    echo "                                      Without URL: shows current configuration"
    echo "                                      With URL: sets the API URL"
    echo ""
    echo "API URL Priority:"
    echo "  1. MOLNOS_API_URL environment variable"
    echo "  2. Configured URL (set via 'molnos configure url')"
    echo "  3. Default (http://localhost:3000)"
    echo ""
    echo "Examples:"
    echo "  molnos configure url                              # Show current URL"
    echo "  molnos configure url https://api.molnos.cloud/prod  # Set production URL"
    echo "  molnos configure url http://localhost:3000        # Reset to default"
    echo ""
}

show_context_help() {
    echo "Context Commands:"
    echo ""
    echo "  context list                      List all contexts"
    echo "  context create <name> [intent] [attributes]"
    echo "                                    Create a new context"
    echo "  context get <name>                Get context details with resources"
    echo "  context update <name> <json>      Update context intent/attributes"
    echo "  context delete <name>             Delete context (keeps resources)"
    echo "  context destroy <name>            Delete context AND all its resources"
    echo "  context generate <name> [options] Generate code for context using AI"
    echo "  context generations <name>        List generations for context"
    echo ""
    echo "Generate Options:"
    echo "  --intent <text>                   Override or supplement the context intent"
    echo "  --resource-types <types>          Comma-separated: functions,sites"
    echo "  --feedback <text>                 Feedback for refining a previous generation"
    echo "  --previous-attempt <id>           ID of previous generation to iterate on"
    echo "  --provider <provider>             Override AI provider (anthropic, openai, ollama, evroc)"
    echo "  --model <model>                   Override AI model"
    echo "  --api-key <key>                   User-provided API key for AI provider"
    echo ""
    echo "Examples:"
    echo "  molnos context create billing \"Billing system resources\""
    echo "  molnos context update billing '{\"intent\":\"Updated billing system\"}'"
    echo "  molnos context destroy billing   # WARNING: Deletes all resources!"
    echo "  molnos context generate billing --intent \"Build a URL shortener API\""
    echo "  molnos context generations billing"
    echo ""
}

show_generation_help() {
    echo "Generation Commands:"
    echo ""
    echo "  generation get <id>               Get generation details"
    echo "  generation delete <id>            Delete a generation"
    echo "  generation apply <id>             Apply generation (deploy code and IAC)"
    echo "  generation discard <id>           Discard a generation (mark as not applied)"
    echo ""
    echo "See also: 'molnos context generate' and 'molnos context generations'"
    echo ""
    echo "Examples:"
    echo "  molnos generation get abc123"
    echo "  molnos generation apply abc123"
    echo "  molnos generation discard abc123"
    echo ""
}

show_iac_help() {
    echo "Infrastructure-as-Code Commands:"
    echo ""
    echo "  iac validate <file>               Validate IAC configuration"
    echo "  iac apply <file> [--prune]        Apply IAC configuration"
    echo "                                      --prune: Delete resources not in config"
    echo "  iac diff <file>                   Preview what changes would be made"
    echo ""
    echo "The IAC file should be a JSON file with the following structure:"
    echo "  {"
    echo "    \"context\": \"my-context\","
    echo "    \"intent\": \"Description of resources\","
    echo "    \"resources\": {"
    echo "      \"functions\": [...],      "
    echo "      \"databases\": [...],"
    echo "      \"storage\": [...],"
    echo "      \"sites\": [...]"
    echo "    }"
    echo "  }"
    echo ""
    echo "Examples:"
    echo "  molnos iac validate molnos.json"
    echo "  molnos iac diff molnos.json"
    echo "  molnos iac apply molnos.json"
    echo "  molnos iac apply molnos.json --prune   # Sync: removes unlisted resources"
    echo ""
}

# ============================================================================
# Global Flag Parser
# ============================================================================

# Parse global flags before command processing
while [[ $# -gt 0 ]]; do
    case "$1" in
        --token)
            if [ -z "${2:-}" ]; then
                print_error "Missing value for --token flag"
                exit 1
            fi
            EXPLICIT_TOKEN="$2"
            shift 2
            ;;
        --token=*)
            EXPLICIT_TOKEN="${1#*=}"
            shift
            ;;
        --force|-f)
            FORCE_FLAG=true
            shift
            ;;
        --version|-v)
            echo "MolnOS CLI v$VERSION"
            exit 0
            ;;
        *)
            # Not a global flag, stop parsing
            break
            ;;
    esac
done

# ============================================================================
# Main Command Handler
# ============================================================================

case "$1" in
    # Server Management
    install)
        molnos_install
        ;;
    init)
        molnos_init
        ;;
    start)
        shift
        molnos_start "$@"
        ;;
    upgrade)
        shift
        molnos_upgrade "$@"
        ;;
    uninstall)
        molnos_uninstall
        ;;

    # Health
    health)
        molnos_health
        ;;

    # Authentication
    auth)
        case "$2" in
            login)
                shift 2
                molnos_login "$@"
                ;;
            verify)
                molnos_verify "$3" "$4"
                ;;
            refresh)
                molnos_refresh "$3"
                ;;
            logout)
                molnos_logout
                ;;
            whoami)
                molnos_whoami
                ;;
            status)
                molnos_auth_status
                ;;
            configure)
                molnos_auth_configure
                ;;
            oauth)
                case "$3" in
                    providers)
                        molnos_oauth_providers
                        ;;
                    initiate)
                        molnos_oauth_initiate "$4" "$5"
                        ;;
                    callback)
                        molnos_oauth_callback "$4" "$5" "$6"
                        ;;
                    *)
                        print_error "Unknown OAuth command: $3"
                        echo ""
                        echo "Available OAuth commands:"
                        echo "  providers           List available OAuth providers"
                        echo "  initiate <provider> [redirect-uri]  Initiate OAuth flow"
                        echo "  callback <provider> <code> [state]  Process OAuth callback"
                        exit 1
                        ;;
                esac
                ;;
            *)
                show_auth_help
                exit 1
                ;;
        esac
        ;;

    # Applications
    apps)
        case "$2" in
            list)
                molnos_apps_list
                ;;
            create)
                shift 2
                molnos_app_create "$@"
                ;;
            get)
                molnos_app_get "$3"
                ;;
            update)
                molnos_app_update "$3" "$4"
                ;;
            delete)
                molnos_app_delete "$3"
                ;;
            *)
                show_apps_help
                exit 1
                ;;
        esac
        ;;

    # Identities
    identities)
        case "$2" in
            list)
                molnos_identities_list
                ;;
            *)
                show_identities_help
                exit 1
                ;;
        esac
        ;;

    # Users
    users)
        case "$2" in
            list)
                molnos_users_list
                ;;
            create)
                molnos_user_create "$3" "$4" "$5"
                ;;
            get)
                molnos_user_get "$3"
                ;;
            update)
                molnos_user_update "$3" "$4"
                ;;
            delete)
                molnos_user_delete "$3"
                ;;
            *)
                show_users_help
                exit 1
                ;;
        esac
        ;;

    # Service Accounts
    service-accounts)
        case "$2" in
            list)
                molnos_service_accounts_list
                ;;
            create)
                molnos_service_account_create "$3" "$4" "$5"
                ;;
            get)
                molnos_service_account_get "$3"
                ;;
            update)
                molnos_service_account_update "$3" "$4"
                ;;
            delete)
                molnos_service_account_delete "$3"
                ;;
            rotate-key)
                molnos_service_account_rotate "$3"
                ;;
            *)
                show_service_accounts_help
                exit 1
                ;;
        esac
        ;;

    # Roles
    roles)
        case "$2" in
            list)
                molnos_roles_list
                ;;
            get)
                molnos_role_get "$3"
                ;;
            create)
                molnos_role_create "$3"
                ;;
            update)
                molnos_role_update "$3" "$4"
                ;;
            delete)
                molnos_role_delete "$3"
                ;;
            *)
                show_roles_help
                exit 1
                ;;
        esac
        ;;

    # Services
    services)
        case "$2" in
            list)
                molnos_services_list
                ;;
            register)
                molnos_service_register "$3"
                ;;
            get)
                molnos_service_get "$3"
                ;;
            update)
                molnos_service_update "$3" "$4"
                ;;
            remove)
                molnos_service_remove "$3"
                ;;
            start)
                molnos_service_start_cmd "$3"
                ;;
            stop)
                molnos_service_stop "$3"
                ;;
            restart)
                molnos_service_restart "$3"
                ;;
            logs)
                molnos_service_logs "$3" "$4" "$5"
                ;;
            *)
                show_services_help
                exit 1
                ;;
        esac
        ;;

    # Database
    db)
        case "$2" in
            tables)
                molnos_db_tables_list
                ;;
            table)
                case "$3" in
                    get)
                        molnos_db_table_get "$4"
                        ;;
                    size)
                        molnos_db_table_size "$4"
                        ;;
                    create)
                        molnos_db_table_create "$4" "$5"
                        ;;
                    delete)
                        molnos_db_table_delete "$4"
                        ;;
                    items)
                        molnos_db_table_items "$4"
                        ;;
                    *)
                        echo "Usage: molnos db table {get|size|create|delete|items}"
                        exit 1
                        ;;
                esac
                ;;
            get)
                molnos_db_get "$3" "$4"
                ;;
            write)
                molnos_db_write "$3" "$4" "$5"
                ;;
            delete)
                molnos_db_delete "$3" "$4"
                ;;
            *)
                show_db_help
                exit 1
                ;;
        esac
        ;;

    # Functions
    functions)
        case "$2" in
            list)
                molnos_functions_list
                ;;
            deploy)
                shift 2
                molnos_function_deploy "$@"
                ;;
            get)
                molnos_function_get "$3"
                ;;
            config)
                molnos_function_config "$3"
                ;;
            update)
                shift 2
                molnos_function_update "$@"
                ;;
            delete)
                molnos_function_delete "$3"
                ;;
            invoke)
                molnos_function_invoke "$3" "$4" "$5"
                ;;
            stats)
                molnos_function_stats
                ;;
            *)
                show_functions_help
                exit 1
                ;;
        esac
        ;;

    # Storage
    storage)
        case "$2" in
            buckets)
                molnos_storage_buckets_list
                ;;
            bucket)
                case "$3" in
                    create)
                        shift 3  # Remove 'storage', 'bucket', 'create'
                        molnos_storage_bucket_create "$@"
                        ;;
                    get)
                        molnos_storage_bucket_get "$4"
                        ;;
                    update)
                        shift 3  # Remove 'storage', 'bucket', 'update'
                        molnos_storage_bucket_update "$@"
                        ;;
                    delete)
                        molnos_storage_bucket_delete "$4"
                        ;;
                    *)
                        echo "Usage: molnos storage bucket {create|get|update|delete}"
                        exit 1
                        ;;
                esac
                ;;
            objects)
                case "$3" in
                    list)
                        molnos_storage_objects_list "$4" "$5"
                        ;;
                    *)
                        echo "Usage: molnos storage objects list"
                        exit 1
                        ;;
                esac
                ;;
            object)
                case "$3" in
                    put)
                        molnos_storage_object_put "$4" "$5" "$6"
                        ;;
                    upload)
                        molnos_storage_object_upload "$4" "$5" "$6"
                        ;;
                    get)
                        molnos_storage_object_get "$4" "$5"
                        ;;
                    delete)
                        molnos_storage_object_delete "$4" "$5"
                        ;;
                    sign)
                        molnos_storage_object_sign "$4" "$5" "$6"
                        ;;
                    *)
                        echo "Usage: molnos storage object {put|upload|get|delete|sign}"
                        exit 1
                        ;;
                esac
                ;;
            *)
                show_storage_help
                exit 1
                ;;
        esac
        ;;

    # Sites
    sites)
        case "$2" in
            list)
                molnos_sites_list
                ;;
            deploy)
                shift 2  # Remove 'sites' and 'deploy' from args
                molnos_site_deploy "$@"
                ;;
            download)
                molnos_site_download "$3"
                ;;
            delete)
                molnos_site_delete "$3"
                ;;
            *)
                show_sites_help
                exit 1
                ;;
        esac
        ;;

    # Logs/Observability
    logs)
        case "$2" in
            query)
                shift 2
                molnos_logs_query "$@"
                ;;
            event)
                molnos_log_event "$3"
                ;;
            stats)
                molnos_logs_stats
                ;;
            cleanup)
                molnos_logs_cleanup "$3"
                ;;
            flush)
                molnos_logs_flush
                ;;
            metrics)
                molnos_system_metrics
                ;;
            *)
                show_logs_help
                exit 1
                ;;
        esac
        ;;

    # Configuration
    configure)
        case "$2" in
            url)
                molnos_configure_url "$3"
                ;;
            *)
                show_configure_help
                exit 1
                ;;
        esac
        ;;

    # Contexts
    context)
        case "$2" in
            list)
                molnos_contexts_list
                ;;
            create)
                molnos_context_create "$3" "$4" "$5"
                ;;
            get)
                molnos_context_get "$3"
                ;;
            update)
                molnos_context_update "$3" "$4"
                ;;
            delete)
                molnos_context_delete "$3"
                ;;
            destroy)
                molnos_context_destroy "$3"
                ;;
            generate)
                shift 2
                molnos_context_generate "$@"
                ;;
            generations)
                molnos_context_generations "$3"
                ;;
            *)
                show_context_help
                exit 1
                ;;
        esac
        ;;

    # AI Generation Management
    generation)
        case "$2" in
            get)
                molnos_generation_get "$3"
                ;;
            delete)
                molnos_generation_delete "$3"
                ;;
            apply)
                molnos_generation_apply "$3"
                ;;
            discard)
                molnos_generation_discard "$3"
                ;;
            *)
                show_generation_help
                exit 1
                ;;
        esac
        ;;

    # IAC (Infrastructure as Code)
    iac)
        case "$2" in
            validate)
                molnos_iac_validate "$3"
                ;;
            apply)
                shift 2
                molnos_iac_apply "$@"
                ;;
            diff)
                molnos_iac_diff "$3"
                ;;
            *)
                show_iac_help
                exit 1
                ;;
        esac
        ;;

    # Schemas
    schemas)
        case "$2" in
            list)
                molnos_schemas_list
                ;;
            create)
                molnos_schema_create "$3"
                ;;
            get)
                molnos_schema_get "$3"
                ;;
            update)
                molnos_schema_update "$3" "$4"
                ;;
            delete)
                molnos_schema_delete "$3"
                ;;
            version)
                molnos_schema_version "$3" "$4"
                ;;
            *)
                show_schemas_help
                exit 1
                ;;
        esac
        ;;

    # Documentation
    legal)
        molnos_legal
        ;;
    docs)
        molnos_docs
        ;;

    # Help
    help|--help|-h)
        show_help
        ;;

    # Version
    version)
        echo "MolnOS CLI v$VERSION"
        ;;

    # Default
    *)
        show_help
        exit 1
        ;;
esac
