#!/bin/bash
set -euo pipefail

# Debug mode - set MORPHBOX_DEBUG=1 to enable
if [[ "${MORPHBOX_DEBUG:-0}" == "1" ]]; then
    set -x  # Enable command tracing
fi

# Mark this as packaged version for different behavior
export MORPHBOX_PACKAGED="true"

# MorphBox Launcher - Packaged version

# CRITICAL: Capture current directory BEFORE any cd commands
# This ensures we get the user's actual working directory
INITIAL_PWD="$(pwd)"

# Get script directory FIRST before we need it
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd .. && pwd )"
WEB_DIR="$SCRIPT_DIR"

# Define color codes early
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

# Define logging functions early so they can be used anywhere
info() { echo -e "${GREEN}[INFO]${NC} $1"; }
error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }

# Early output so user knows script is running
info "Starting MorphBox..."

# Lock mechanism removed - multiple instances are allowed to run

# Load config from .morphbox.env if exists
if [[ -f "$SCRIPT_DIR/.morphbox.env" ]]; then
    source "$SCRIPT_DIR/.morphbox.env"
fi

# Default to local only
BIND_HOST="${MORPHBOX_HOST:-localhost}"
ACCESS_MODE="${MORPHBOX_BIND_MODE:-local}"
DEV_MODE=false
AUTH_ENABLED=false
TERMINAL_MODE=false
MORPHBOX_AUTH_USERNAME=""
MORPHBOX_AUTH_PASSWORD=""

# Port variables (will be set dynamically)
WEB_PORT=""
WS_PORT=""

# Apply bind mode
if [[ "$ACCESS_MODE" == "external" ]]; then
    BIND_HOST="0.0.0.0"
fi

# Parse arguments
while [[ $# -gt 0 ]]; do
    case $1 in
        --external)
            BIND_HOST="0.0.0.0"
            ACCESS_MODE="external"
            shift
            ;;
        --local)
            BIND_HOST="localhost"
            ACCESS_MODE="local"
            shift
            ;;
        --vpn)
            info "Detecting VPN interface..."
            # Auto-detect VPN interface IP (works on both Mac and Linux)
            if [[ "$(uname)" == "Darwin" ]]; then
                # Mac: Find VPN interfaces and get the first valid IP
                # Look for utun*, tailscale*, tun*, wg* interfaces with real IPs
                VPN_IP=""
                # Temporarily disable exit on error for interface detection
                set +e
                IFACES=$(ifconfig -l | tr ' ' '\n' | grep -E '^(utun|tailscale|tun|wg)[0-9]+$')
                set -e
                for iface in $IFACES; do
                    IP=$(ifconfig "$iface" 2>/dev/null | grep "inet " | awk '{print $2}' || true)
                    # Skip if no IP, loopback, or link-local
                    if [[ -n "$IP" ]] && [[ "$IP" != "127."* ]] && [[ "$IP" != "169.254."* ]]; then
                        VPN_IP="$IP"
                        break
                    fi
                done
            else
                # Linux: use ip addr show
                VPN_IP=$(ip addr show 2>/dev/null | grep -E "tailscale0|tun0|utun|wg0" | grep "inet " | awk '{print $2}' | cut -d/ -f1 | head -n1)
            fi

            if [[ -n "$VPN_IP" ]]; then
                BIND_HOST="$VPN_IP"
                ACCESS_MODE="vpn"
                info "Detected VPN IP: $VPN_IP"
            else
                warn "No VPN interface detected, falling back to external mode"
                BIND_HOST="0.0.0.0"
                ACCESS_MODE="external"
            fi
            shift
            ;;
        --auth)
            AUTH_ENABLED=true
            shift
            ;;
        --terminal)
            TERMINAL_MODE=true
            shift
            ;;
        --dev)
            DEV_MODE=true
            shift
            ;;
        --help)
            echo "MorphBox Launcher"
            echo ""
            echo "Usage: $0 [OPTIONS]"
            echo ""
            echo "Options:"
            echo "  --local     Bind to localhost only (default)"
            echo "  --external  Bind to all interfaces (WARNING: exposes to network)"
            echo "  --vpn       Auto-detect and bind to VPN interface (Tailscale, WireGuard, etc.)"
            echo "  --terminal  Terminal mode - Claude Code only, no panels"
            echo "  --auth      Enable authentication (mandatory for --external, optional for --vpn)"
            echo "  --dev       Skip security warnings (development mode)"
            echo "  --help      Show this help message"
            echo ""
            echo "Examples:"
            echo "  $0              # Start locally (safe)"
            echo "  $0 --terminal   # Claude Code only mode"
            echo "  $0 --external   # Expose to network with mandatory auth"
            echo "  $0 --vpn       # Bind to VPN interface only"
            echo "  $0 --vpn --auth # VPN mode with authentication"
            echo "  $0 --external --dev   # External mode without prompts"
            exit 0
            ;;
        *)
            error "Unknown option: $1. Use --help for usage."
            ;;
    esac
done

# Check dependencies
if ! command -v node > /dev/null; then
    error "Node.js is not installed. Please install Node.js 18 or later"
fi

# Setup authentication
if [[ "$ACCESS_MODE" == "external" ]] || ([[ "$ACCESS_MODE" == "vpn" ]] && [[ "$AUTH_ENABLED" == "true" ]]); then
    # External mode always requires auth, VPN mode only if --auth is specified
    if [[ "$ACCESS_MODE" == "external" ]]; then
        AUTH_ENABLED=true
        export MORPHBOX_AUTH_MODE="external"
    else
        export MORPHBOX_AUTH_MODE="vpn"
    fi
    
    # Generate secure credentials if not provided
    if [[ -z "$MORPHBOX_AUTH_USERNAME" ]]; then
        export MORPHBOX_AUTH_USERNAME="admin"
    fi
    
    if [[ -z "$MORPHBOX_AUTH_PASSWORD" ]]; then
        # Generate a secure random password
        export MORPHBOX_AUTH_PASSWORD=$(openssl rand -base64 12)
        info "🔐 Generated authentication credentials:"
        info "   Username: $MORPHBOX_AUTH_USERNAME"
        info "   Password: $MORPHBOX_AUTH_PASSWORD"
        info "   Save these credentials - you'll need them to access MorphBox!"
    fi
    
    export MORPHBOX_AUTH_ENABLED="true"
else
    export MORPHBOX_AUTH_MODE="none"
    export MORPHBOX_AUTH_ENABLED="false"
fi

# Show security warning if external (unless in dev mode)
if [[ "$ACCESS_MODE" == "external" ]] && [[ "$DEV_MODE" != "true" ]]; then
    echo ""
    echo -e "${RED}████████████████████████████████████████████████████████████████${NC}"
    echo -e "${RED}█                                                              █${NC}"
    echo -e "${RED}█  🚨 EXTREME SECURITY WARNING - READ CAREFULLY! 🚨            █${NC}"
    echo -e "${RED}█                                                              █${NC}"
    echo -e "${RED}████████████████████████████████████████████████████████████████${NC}"
    echo ""
    warn "You are about to expose your ENTIRE DEVELOPMENT ENVIRONMENT to the network!"
    echo ""
    warn "This means ANYONE on your network can:"
    warn "  ❌ Execute ANY command on your system"
    warn "  ❌ Read, modify, or DELETE any accessible file"
    warn "  ❌ Steal your source code and secrets"
    warn "  ❌ Install malware or backdoors"
    warn "  ❌ Use your machine to attack others"
    echo ""
    warn "Authentication is enabled but is NOT sufficient protection!"
    echo ""
    warn "ONLY proceed if ALL of these are true:"
    warn "  ✅ You are on an isolated, air-gapped network"
    warn "  ✅ This machine contains NO sensitive data"
    warn "  ✅ This machine has NO production access"
    warn "  ✅ You understand and accept these risks"
    echo ""
    echo -e "${RED}If you're unsure, the answer is NO. Press 'n' to cancel.${NC}"
    echo ""
    read -p "Type 'I UNDERSTAND THE RISKS' to continue: " -r CONFIRM
    echo ""
    if [[ "$CONFIRM" != "I UNDERSTAND THE RISKS" ]]; then
        info "Aborted. Good choice! Use --vpn for safer remote access."
        exit 0
    fi
elif [[ "$ACCESS_MODE" == "vpn" ]]; then
    info "✅ VPN mode: MorphBox will only be accessible via VPN connection"
    info "Binding to: $BIND_HOST"
    if [[ "$AUTH_ENABLED" == "true" ]]; then
        info "🔐 Authentication is enabled for additional security"
    fi
fi

# Function to check if port is in use and by what
check_port_usage() {
    local port=$1
    local bind_ip=$2

    # OS-specific port checking
    if [[ "$(uname)" == "Darwin" ]]; then
        # Mac: use lsof to check port usage
        local lsof_output=$(lsof -i TCP:${port} -P 2>/dev/null | grep LISTEN)
        if [[ -n "$lsof_output" ]]; then
            # Get the process name and PID
            local pid=$(echo "$lsof_output" | awk '{print $2}' | head -1)
            if [[ -n "$pid" ]]; then
                # Check if it's a morphbox process
                if ps -p "$pid" -o args= 2>/dev/null | grep -qE "morphbox|server-packaged|websocket-proxy"; then
                    return 0  # It's morphbox
                else
                    return 1  # It's another process
                fi
            fi
        fi
    else
        # Linux: use netstat/ss
        if netstat -tulpn 2>/dev/null | grep -q "${bind_ip}:${port}" || ss -tulpn 2>/dev/null | grep -q "${bind_ip}:${port}"; then
            # Get the process using this port
            local pid=$(ss -tulpn 2>/dev/null | grep "${bind_ip}:${port}" | grep -oP 'pid=\K[0-9]+' | head -1)
            if [[ -n "$pid" ]]; then
                local pname=$(ps -p "$pid" -o comm= 2>/dev/null || echo "unknown")
                # Check if it's a morphbox process
                if ps -p "$pid" -o args= 2>/dev/null | grep -qE "morphbox|server-packaged|websocket-proxy"; then
                    return 0  # It's morphbox
                else
                    return 1  # It's another process
                fi
            fi
        fi
    fi
    return 2  # Port is free
}

# Removed cleanup_morphbox_processes function - not needed for multi-instance support

# Check for existing instances on our target ports
check_existing_instance() {
    local need_cleanup=false
    
    # Check port 8008
    set +e  # Temporarily disable error checking
    check_port_usage 8008 "$BIND_HOST"
    local status=$?
    set -e  # Re-enable error checking
    if [[ $status -eq 0 ]]; then
        warn "MorphBox is already running on ${BIND_HOST}:8008"
        need_cleanup=true
    elif [[ $status -eq 1 ]]; then
        error "Port ${BIND_HOST}:8008 is in use by another process. Please free the port and try again."
    fi
    
    # Check port 8009
    set +e  # Temporarily disable error checking
    check_port_usage 8009 "$BIND_HOST"
    status=$?
    set -e  # Re-enable error checking
    if [[ $status -eq 0 ]]; then
        warn "MorphBox WebSocket proxy is already running on ${BIND_HOST}:8009"
        need_cleanup=true
    elif [[ $status -eq 1 ]]; then
        error "Port ${BIND_HOST}:8009 is in use by another process. Please free the port and try again."
    fi
    
    if [[ "$need_cleanup" == "true" ]]; then
        error "Cannot start: Ports are already in use by another MorphBox instance"
    fi
}

# Find available ports
info "Finding available ports..."

# Check if port-finder exists
if [[ ! -f "$SCRIPT_DIR/scripts/port-finder.js" ]]; then
    warn "Port finder not found, using default ports"
    WEB_PORT=8008
    WS_PORT=8009
else
    # Try to run port-finder (only capture stdout, let stderr go to console)
    PORT_RESULT=$(node "$SCRIPT_DIR/scripts/port-finder.js" find "$BIND_HOST")
    PORT_FINDER_EXIT=$?

    if [[ $PORT_FINDER_EXIT -ne 0 ]]; then
        warn "Port finder failed with exit code $PORT_FINDER_EXIT"
        warn "Port finder output: $PORT_RESULT"
        warn "Using default ports as fallback"
        WEB_PORT=8008
        WS_PORT=8009
    else
        # Parse the port result (using sed for compatibility, jq might not be available)
        WEB_PORT=$(echo $PORT_RESULT | sed -n 's/.*"webPort":\([0-9]*\).*/\1/p')
        WS_PORT=$(echo $PORT_RESULT | sed -n 's/.*"wsPort":\([0-9]*\).*/\1/p')

        if [[ -z "$WEB_PORT" ]] || [[ -z "$WS_PORT" ]]; then
            warn "Failed to parse port information from: $PORT_RESULT"
            warn "Using default ports as fallback"
            WEB_PORT=8008
            WS_PORT=8009
        fi
    fi
fi

info "Using ports: $WEB_PORT (web), $WS_PORT (websocket)"

# Use shared container for all instances
CONTAINER_NAME="morphbox-vm"
# Use fixed SSH port for the shared container
SSH_PORT=2222

info "Using shared container: $CONTAINER_NAME"
info "SSH port: $SSH_PORT"

# Don't clean up processes - we support multiple instances
# Each instance uses unique ports so they don't conflict
# cleanup_morphbox_processes - DISABLED for multi-instance support

# Start Docker container if not running
info "Checking Docker container..."

# Get the user's current directory (absolute path)
# This is where the user ran 'morphbox' from, NOT where the script is located
# Use MORPHBOX_USER_DIR if set by wrapper, otherwise use INITIAL_PWD captured at script start
USER_DIR="${MORPHBOX_USER_DIR:-$INITIAL_PWD}"
info "User workspace: $USER_DIR"

# Get the current morphbox version for checking
MORPHBOX_VERSION=$(node -e "console.log(require('$SCRIPT_DIR/package.json').version)" 2>/dev/null || echo "unknown")

# Check if container exists (running or stopped)
if docker ps -a | grep -q "$CONTAINER_NAME"; then
    # Container exists - check version, workspace, and state
    CONTAINER_IMAGE=$(docker inspect "$CONTAINER_NAME" --format '{{ .Config.Image }}' 2>/dev/null || echo "")
    CONTAINER_IMAGE_VERSION=$(docker image inspect "$CONTAINER_IMAGE" --format '{{index .Config.Labels "morphbox.version"}}' 2>/dev/null || echo "")
    CONTAINER_WORKSPACE=$(docker inspect "$CONTAINER_NAME" --format '{{ range .Mounts }}{{ if eq .Destination "/workspace" }}{{ .Source }}{{ end }}{{ end }}')

    # Check version mismatch
    if [[ "$CONTAINER_IMAGE_VERSION" != "$MORPHBOX_VERSION" ]]; then
        info "Container version mismatch: running $CONTAINER_IMAGE_VERSION, package is $MORPHBOX_VERSION"
        info "Recreating container with updated version..."
        docker stop "$CONTAINER_NAME" 2>/dev/null || true
        docker rm "$CONTAINER_NAME" 2>/dev/null || true
        NEED_CREATE=true
    elif [[ "$CONTAINER_WORKSPACE" != "$USER_DIR" ]]; then
        # Workspace mismatch - MUST recreate container with correct mount
        # This is core MorphBox functionality - the container must always
        # use the current directory as workspace
        info "Workspace changed from $CONTAINER_WORKSPACE to $USER_DIR"
        info "Recreating container with correct workspace..."
        docker stop "$CONTAINER_NAME" 2>/dev/null || true
        docker rm "$CONTAINER_NAME" 2>/dev/null || true
        NEED_CREATE=true
    elif ! docker ps | grep -q "$CONTAINER_NAME"; then
        info "Starting existing MorphBox VM container (v$CONTAINER_IMAGE_VERSION)..."
        docker start "$CONTAINER_NAME"
        sleep 2
        NEED_CREATE=false
    else
        info "MorphBox VM container already running (v$CONTAINER_IMAGE_VERSION)"
        NEED_CREATE=false
    fi
else
    NEED_CREATE=true
fi

if [[ "$NEED_CREATE" == "true" ]]; then
    info "Creating MorphBox VM container with workspace: $USER_DIR"
    info "MorphBox package version: $MORPHBOX_VERSION"

    # Check if version-specific image exists
    IMAGE_TAG="morphbox:${MORPHBOX_VERSION}"
    if docker image inspect "$IMAGE_TAG" >/dev/null 2>&1; then
        # Check if the image has the correct version label
        IMAGE_LABEL_VERSION=$(docker image inspect "$IMAGE_TAG" --format '{{index .Config.Labels "morphbox.version"}}' 2>/dev/null || echo "")

        if [[ "$IMAGE_LABEL_VERSION" == "$MORPHBOX_VERSION" ]]; then
            info "Using existing $IMAGE_TAG image (version verified)"
            IMAGE_EXISTS=true
        else
            warn "Image $IMAGE_TAG exists but has wrong version label ($IMAGE_LABEL_VERSION)"
            warn "Rebuilding to ensure correct version..."
            docker rmi -f "$IMAGE_TAG" 2>/dev/null || true
            IMAGE_EXISTS=false
        fi
    else
        warn "$IMAGE_TAG image not found - will build it now"
        warn "This may take a few minutes on first run..."
        IMAGE_EXISTS=false
    fi

    # Find available dev server ports (5173-5179)
    info "Checking for available dev server ports..."
    DEV_PORT_MAPPINGS=""
    for port in {5173..5179}; do
        # Check if port is available on BIND_HOST
        set +e  # Temporarily disable error checking
        if [[ "$(uname)" == "Darwin" ]]; then
            # Mac: use lsof
            lsof -i TCP:${port} -sTCP:LISTEN 2>/dev/null | grep -q "${BIND_HOST}:${port}"
            port_in_use=$?
        else
            # Linux: use ss
            ss -tulpn 2>/dev/null | grep -q "${BIND_HOST}:${port}"
            port_in_use=$?
        fi
        set -e  # Re-enable error checking

        if [[ $port_in_use -ne 0 ]]; then
            # Port is available
            DEV_PORT_MAPPINGS="${DEV_PORT_MAPPINGS}      - \"${BIND_HOST}:${port}:${port}\"
"
        fi
    done

    if [[ -n "$DEV_PORT_MAPPINGS" ]]; then
        info "Exposing available dev server ports on ${BIND_HOST}"
    fi

    # Create a temporary docker-compose file with absolute paths
    TEMP_COMPOSE="/tmp/morphbox-compose-$$.yml"

    if [[ "$IMAGE_EXISTS" == "true" ]]; then
        # Use the pre-built image
        cat > "$TEMP_COMPOSE" << EOF
services:
  morphbox-vm:
    image: $IMAGE_TAG
    container_name: $CONTAINER_NAME
    hostname: $CONTAINER_NAME
    ports:
      - "$SSH_PORT:22"  # SSH port mapping (unique per instance)
${DEV_PORT_MAPPINGS}    volumes:
      # Persist Claude authentication data (shared across instances)
      - claude-config:/home/morphbox/.config/claude-code
      # Mount USER'S CURRENT DIRECTORY as workspace (absolute path)
      - $USER_DIR:/workspace
      # Mount morphbox package directory for access to project files
      - $SCRIPT_DIR:/workspace/morphbox
      # Persist bash history and other user data (shared across instances)
      - claude-home:/home/morphbox
      # Persist AI tools and updates
      - claude-npm-cache:/usr/local/lib/node_modules
      - claude-npm-bin:/usr/local/bin
    environment:
      - TERM=xterm-256color
      - COLORTERM=truecolor
      - ANTHROPIC_API_KEY=\${ANTHROPIC_API_KEY:-}
    restart: unless-stopped
    networks:
      - morphbox-network
EOF
    else
        # Build the image with version tag
        cat > "$TEMP_COMPOSE" << EOF
services:
  morphbox-vm:
    build:
      context: $SCRIPT_DIR/docker
      dockerfile: Dockerfile
      args:
        - MORPHBOX_VERSION=$MORPHBOX_VERSION
    image: $IMAGE_TAG
    container_name: $CONTAINER_NAME
    hostname: $CONTAINER_NAME
    ports:
      - "$SSH_PORT:22"  # SSH port mapping (unique per instance)
${DEV_PORT_MAPPINGS}    volumes:
      # Persist Claude authentication data (shared across instances)
      - claude-config:/home/morphbox/.config/claude-code
      # Mount USER'S CURRENT DIRECTORY as workspace (absolute path)
      - $USER_DIR:/workspace
      # Mount morphbox package directory for access to project files
      - $SCRIPT_DIR:/workspace/morphbox
      # Persist bash history and other user data (shared across instances)
      - claude-home:/home/morphbox
      # Persist AI tools and updates
      - claude-npm-cache:/usr/local/lib/node_modules
      - claude-npm-bin:/usr/local/bin
    environment:
      - TERM=xterm-256color
      - COLORTERM=truecolor
      - ANTHROPIC_API_KEY=\${ANTHROPIC_API_KEY:-}
    restart: unless-stopped
    networks:
      - morphbox-network
EOF
    fi

    # Add the volumes and networks sections (same for both)
    cat >> "$TEMP_COMPOSE" << EOF

networks:
  morphbox-network:
    driver: bridge

volumes:
  claude-config:
    driver: local
  claude-home:
    driver: local
  claude-npm-cache:
    driver: local
  claude-npm-bin:
    driver: local
EOF

    # Use the temporary compose file to create container
    if [[ "$IMAGE_EXISTS" == "false" ]]; then
        # Build the image using Docker's caching mechanism
        # Only rebuild layers that have changed
        info "Building Docker image (this may take a few minutes on first run)..."
        info "Using Docker layer caching to speed up subsequent builds..."
        docker compose -f "$TEMP_COMPOSE" build morphbox-vm
        info "Docker image built successfully"
    fi

    # Start the container
    docker compose -f "$TEMP_COMPOSE" up -d

    # Clean up temp file
    rm -f "$TEMP_COMPOSE"

    sleep 2
fi

# Check for Claude updates in container
check_claude_updates() {
    info "Checking for Claude updates..."
    
    # Get current version
    CURRENT_VERSION=$(docker exec -u morphbox "$CONTAINER_NAME" npm list -g @anthropic-ai/claude-code 2>/dev/null | grep '@anthropic-ai/claude-code@' | sed 's/.*@anthropic-ai\/claude-code@//' | tr -d ' ')
    
    if [[ -z "$CURRENT_VERSION" ]]; then
        warn "Could not determine Claude version"
        return 0
    fi
    
    # Check for updates (this will be silent if already up to date)
    UPDATE_CHECK=$(docker exec -u morphbox "$CONTAINER_NAME" npm outdated -g @anthropic-ai/claude-code 2>/dev/null | grep '@anthropic-ai/claude-code' || true)
    
    if [[ -n "$UPDATE_CHECK" ]]; then
        LATEST_VERSION=$(echo "$UPDATE_CHECK" | awk '{print $4}')
        info "Claude update available: $CURRENT_VERSION → $LATEST_VERSION"
        info "Updating Claude in container..."
        
        if docker exec -u morphbox "$CONTAINER_NAME" npm update -g @anthropic-ai/claude-code > /dev/null 2>&1; then
            NEW_VERSION=$(docker exec -u morphbox "$CONTAINER_NAME" npm list -g @anthropic-ai/claude-code 2>/dev/null | grep '@anthropic-ai/claude-code@' | sed 's/.*@anthropic-ai\/claude-code@//' | tr -d ' ')
            info "Claude updated successfully to version $NEW_VERSION"
        else
            warn "Failed to update Claude - auto-update may still work inside the terminal"
        fi
    else
        info "Claude is up to date (version $CURRENT_VERSION)"
    fi
}

# Run update check
# Disabled for packaged version due to Docker exec issues
# check_claude_updates

# Get local IP for external mode
if [[ "$ACCESS_MODE" == "external" ]]; then
    LOCAL_IP=$(hostname -I | awk '{print $1}')
    WS_URL="ws://${LOCAL_IP}:$WS_PORT"
    WEB_URL="http://${LOCAL_IP}:$WEB_PORT"
else
    WS_URL="ws://localhost:$WS_PORT"
    WEB_URL="http://localhost:$WEB_PORT"
fi

# Terminal mode - run Claude directly in terminal
if [[ "$TERMINAL_MODE" == "true" ]]; then
    info "Launching Claude in terminal mode..."
    
    # Get the current directory
    CURRENT_DIR=$(pwd)
    
    # Determine the working directory in the container
    # Check if we're in the morphbox project directory
    if [[ "$CURRENT_DIR" == "$SCRIPT_DIR"* ]]; then
        # We're inside the morphbox project, which is mounted at /workspace/morphbox
        RELATIVE_PATH="${CURRENT_DIR#$SCRIPT_DIR}"
        CONTAINER_PATH="/workspace/morphbox${RELATIVE_PATH}"
        info "Working in morphbox project directory"
    else
        # We're outside the morphbox project
        # Just start in the default workspace - user can navigate from there
        CONTAINER_PATH="/workspace"
        info "Starting in default workspace directory"
        info "Note: Current directory ($CURRENT_DIR) is not directly accessible"
        info "You can navigate to /workspace/morphbox for the morphbox project"
    fi
    
    echo ""
    
    # Run Claude directly in the Docker container
    # Note: Not using --continue flag in terminal mode so it starts fresh
    docker exec -it \
        -u morphbox \
        -w "$CONTAINER_PATH" \
        -e "TERM=xterm-256color" \
        -e "ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}" \
        "$CONTAINER_NAME" \
        bash -c "claude || bash"
    
    # Exit after Claude exits
    exit 0
fi

# Start WebSocket proxy
info "Starting WebSocket proxy..."
# Set environment variables for WebSocket proxy (no password needed anymore)
HOST="$BIND_HOST" \
PORT=$WS_PORT \
MORPHBOX_WEB_PORT=$WEB_PORT \
MORPHBOX_VM_HOST="localhost" \
MORPHBOX_VM_PORT=$SSH_PORT \
MORPHBOX_VM_USER="morphbox" \
node "$WEB_DIR/websocket-proxy.js" > /tmp/morphbox-websocket-proxy.log 2>&1 &
WS_PID=$!

# Start the packaged server
info "Starting MorphBox server..."
# Don't cd for packaged version - run with full path
MORPHBOX_HOME="$HOME/.morphbox" \
MORPHBOX_HOST="$BIND_HOST" \
MORPHBOX_AUTH_MODE="$MORPHBOX_AUTH_MODE" \
MORPHBOX_AUTH_ENABLED="$MORPHBOX_AUTH_ENABLED" \
MORPHBOX_AUTH_USERNAME="$MORPHBOX_AUTH_USERNAME" \
MORPHBOX_AUTH_PASSWORD="$MORPHBOX_AUTH_PASSWORD" \
HOST="$BIND_HOST" \
PORT=$WEB_PORT \
WS_PORT=$WS_PORT \
node "$WEB_DIR/server-packaged.js" > /tmp/morphbox-server.log 2>&1 &
WEB_PID=$!

# Wait for web server
sleep 3

# Debug: Check if processes are still running
if kill -0 $WEB_PID 2>/dev/null; then
    info "Web server is running (PID: $WEB_PID)"
else
    error "Web server failed to start or died immediately"
fi

if kill -0 $WS_PID 2>/dev/null; then
    info "WebSocket proxy is running (PID: $WS_PID)"
else
    error "WebSocket proxy failed to start or died immediately"
fi

# Store PIDs for tracking
PID_FILE="/tmp/morphbox-${WEB_PORT}.pid"
echo "WEB_PID=$WEB_PID" > "$PID_FILE"
echo "WS_PID=$WS_PID" >> "$PID_FILE"
echo "BIND_HOST=$BIND_HOST" >> "$PID_FILE"
echo "WEB_PORT=$WEB_PORT" >> "$PID_FILE"
echo "WS_PORT=$WS_PORT" >> "$PID_FILE"
echo "CONTAINER_NAME=$CONTAINER_NAME" >> "$PID_FILE"
info "Instance tracking saved to $PID_FILE"

# Save instance information for management
node -e "
import('$SCRIPT_DIR/scripts/port-finder.js').then(({ saveInstance }) => {
  saveInstance({
    webPort: $WEB_PORT,
    wsPort: $WS_PORT,
    host: '$BIND_HOST',
    containerName: '$CONTAINER_NAME',
    workspace: '$USER_DIR',
    pid: process.pid
  });
});
" 2>/dev/null || true

info "MorphBox is running!"
echo ""
if [[ "$TERMINAL_MODE" == "true" ]]; then
    info "🖥️  Terminal Mode - Claude Code only (no panels)"
fi
if [[ "$DEV_MODE" == "true" ]]; then
    info "Development mode enabled (warnings disabled)"
fi
if [[ "$ACCESS_MODE" == "external" ]]; then
    echo -e "${BLUE}External Access Enabled:${NC}"
    info "- Web interface: $WEB_URL"
    info "- Also accessible at: http://${BIND_HOST}:8008"
    info "- WebSocket server: $WS_URL"
    echo ""
    warn "Remember to configure firewall rules if needed"
else
    info "- Web interface: $WEB_URL"
    info "- WebSocket server: $WS_URL"
fi
info ""
info "Press Ctrl+C to stop all services"

# Track if cleanup is already running
CLEANUP_IN_PROGRESS=false

# Cleanup function
cleanup() {
    # Prevent recursive cleanup
    if [[ "$CLEANUP_IN_PROGRESS" == "true" ]]; then
        return
    fi
    CLEANUP_IN_PROGRESS=true
    
    echo ""
    info "Stopping MorphBox..."
    
    # Try to load PIDs from file if not set
    if [[ -z "$WEB_PID" ]] || [[ -z "$WS_PID" ]]; then
        PID_FILE="/tmp/morphbox-${WEB_PORT}.pid"
        if [[ -f "$PID_FILE" ]]; then
            source "$PID_FILE"
        fi
    fi
    
    # Kill ONLY this instance's processes using their PIDs
    if [[ -n "$WEB_PID" ]]; then
        kill $WEB_PID 2>/dev/null || true
        # Wait briefly and force kill if still running
        sleep 0.5
        kill -9 $WEB_PID 2>/dev/null || true
    fi

    if [[ -n "$WS_PID" ]]; then
        kill $WS_PID 2>/dev/null || true
        # Wait briefly and force kill if still running
        sleep 0.5
        kill -9 $WS_PID 2>/dev/null || true
    fi

    # Do NOT use pkill as it kills ALL instances
    
    # Clean up PID file
    rm -f "/tmp/morphbox-${WEB_PORT}.pid" 2>/dev/null || true

    # Remove instance from tracking
    node -e "
    import('$SCRIPT_DIR/scripts/port-finder.js').then(({ removeInstance }) => {
      removeInstance($WEB_PORT);
    });
    " 2>/dev/null || true
    
    # Don't stop the shared Docker container - it's used by all instances
    # Container will persist for other morphbox instances to use
    
    info "MorphBox stopped"
    
    # Exit cleanly without triggering trap again
    trap - SIGINT SIGTERM
    exit 0
}

# Set up signal handler
trap cleanup SIGINT SIGTERM

# Wait for child processes instead of looping with sleep
# This allows signals to be handled immediately
wait $WEB_PID $WS_PID 2>/dev/null

# If we get here, a process exited unexpectedly
warn "Server process stopped unexpectedly"
cleanup