"""
OpenClaw Auto-Login Automation

Cross-platform zero-interaction login to the OpenClaw dashboard.
Works on Windows, Linux, and macOS.

Follows the "How to connect" steps from the dashboard:
1. Start the gateway on your host machine
2. Get a tokenized dashboard URL
3. Open the browser with the authenticated URL
"""

import os
import platform
import subprocess
import sys
import time
import webbrowser
from pathlib import Path
from typing import Optional


def get_install_base() -> Path:
    """Get base installation directory (fully isolated)."""
    system = platform.system()
    if system == "Windows":
        base = Path(os.environ.get("LOCALAPPDATA", Path.home() / "AppData" / "Local"))
        return base / "openclaw-installer"
    else:
        # Use .local/share for fully isolated installation (XDG compliant)
        xdg_data = os.environ.get("XDG_DATA_HOME", Path.home() / ".local" / "share")
        return Path(xdg_data) / "openclaw-installer"


def get_wrapper_path() -> Optional[Path]:
    """Get the path to the openclaw wrapper for the current platform."""
    # Check multiple locations for the openclaw executable
    
    # 1. Check npm global bin (most likely after npm install -g)
    npm_global_bin = get_npm_global_bin_dir()
    if npm_global_bin:
        if platform.system() == "Windows":
            for ext in [".cmd", ".ps1", ""]:
                wrapper = npm_global_bin / f"openclaw{ext}"
                if wrapper.exists():
                    return wrapper
        else:
            wrapper = npm_global_bin / "openclaw"
            if wrapper.exists():
                return wrapper
    
    # 2. Check PATH directly
    which_openclaw = shutil.which("openclaw")
    if which_openclaw:
        return Path(which_openclaw)
    
    # 3. Check isolated bin directory (fallback)
    bin_dir = get_install_base() / "bin"
    if platform.system() == "Windows":
        wrapper = bin_dir / "openclaw.cmd"
    else:
        wrapper = bin_dir / "openclaw"
    
    if wrapper.exists():
        return wrapper
    
    return None


def get_bundled_node_bin() -> Optional[Path]:
    """Get the bundled Node.js bin directory."""
    install_base = get_install_base()
    if platform.system() == "Windows":
        node_bin = install_base / "node"
    else:
        node_bin = install_base / "node" / "bin"
    return node_bin if node_bin.exists() else None


def get_npm_global_bin_dir() -> Optional[Path]:
    """Get npm global bin directory where 'openclaw' command is installed."""
    # First, try with bundled npm (correct PATH)
    bundled_node_bin = get_bundled_node_bin()
    if bundled_node_bin:
        npm_exe = bundled_node_bin / "npm"
        if platform.system() == "Windows":
            npm_exe = bundled_node_bin / "npm.cmd"
        
        if npm_exe.exists():
            try:
                env = os.environ.copy()
                # Prepend bundled node to PATH
                env["PATH"] = str(bundled_node_bin) + os.pathsep + env.get("PATH", "")
                
                result = subprocess.run(
                    [str(npm_exe), "bin", "-g"],
                    capture_output=True,
                    text=True,
                    timeout=10,
                    env=env,
                )
                if result.returncode == 0:
                    return Path(result.stdout.strip())
            except Exception:
                pass
    
    # Fallback: try system npm
    try:
        result = subprocess.run(
            ["npm", "bin", "-g"],
            capture_output=True,
            text=True,
            timeout=10,
        )
        if result.returncode == 0:
            return Path(result.stdout.strip())
    except Exception:
        pass
    
    # Final fallback to platform-specific defaults
    if bundled_node_bin and bundled_node_bin.exists():
        return bundled_node_bin
    
    if platform.system() == "Windows":
        appdata = os.environ.get("APPDATA", str(Path.home() / "AppData" / "Roaming"))
        return Path(appdata) / "npm"
    else:
        return Path.home() / ".local" / "share" / "openclaw-installer" / "node" / "bin"


def get_platform_name() -> str:
    """Get a friendly platform name."""
    system = platform.system()
    if system == "Windows":
        return "Windows"
    elif system == "Darwin":
        return "macOS"
    else:
        return "Linux"


def get_node_path() -> Optional[Path]:
    """
    Get the path to the bundled Node.js executable.
    
    Returns:
        Path to node.exe (Windows) or node (Unix), or None if not found
    """
    install_base = get_install_base()
    
    if sys.platform == "win32":
        node = install_base / "node" / "node.exe"
    else:
        node = install_base / "node" / "bin" / "node"
    
    return node if node.exists() else None


def get_npm_global_root() -> Optional[Path]:
    """Get npm global root directory."""
    try:
        env = get_env_with_node()
        bundled_node_bin = get_bundled_node_bin()
        if bundled_node_bin:
            npm_exe = bundled_node_bin / "npm"
            if platform.system() == "Windows":
                npm_exe = bundled_node_bin / "npm.cmd"
            
            if npm_exe.exists():
                result = subprocess.run(
                    [str(npm_exe), "root", "-g"],
                    capture_output=True,
                    text=True,
                    timeout=10,
                    env=env,
                )
                if result.returncode == 0:
                    return Path(result.stdout.strip())
    except Exception:
        pass
    
    # Fallback to platform-specific defaults
    if platform.system() == "Windows":
        return Path.home() / "AppData" / "Roaming" / "npm" / "node_modules"
    else:
        return Path.home() / ".local" / "share" / "openclaw-installer" / "node" / "lib" / "node_modules"


def get_openclaw_index_path() -> Optional[Path]:
    """
    Get the path to the OpenClaw index.js file.
    
    Returns:
        Path to index.js, or None if not found
    """
    # First check npm global root (where 'npm install -g' puts packages)
    npm_root = get_npm_global_root()
    if npm_root:
        index = npm_root / "openclaw" / "dist" / "index.js"
        if index.exists():
            return index
    
    # Fallback to old local install location
    install_base = get_install_base()
    index = install_base / "openclaw" / "node_modules" / "openclaw" / "dist" / "index.js"
    if index.exists():
        return index
    
    return None


def find_process_using_port(port: int = 18789) -> Optional[tuple[int, str]]:
    """
    Find the process using a specific port.
    
    Returns:
        tuple: (pid, process_name) if found, None otherwise
    """
    system = platform.system()
    
    try:
        if system == "Windows":
            # Windows: use netstat and findstr
            result = subprocess.run(
                ["netstat", "-ano", "|", "findstr", f":{port}"],
                capture_output=True,
                text=True,
                shell=True,
                timeout=10,
            )
            if result.returncode == 0 and result.stdout:
                # Parse netstat output to find PID
                for line in result.stdout.split("\n"):
                    if f":{port}" in line and ("LISTENING" in line or "ESTABLISHED" in line):
                        parts = line.strip().split()
                        if len(parts) >= 5:
                            pid = int(parts[-1])
                            # Get process name
                            proc_result = subprocess.run(
                                ["tasklist", "/FI", f"PID eq {pid}", "/FO", "CSV", "/NH"],
                                capture_output=True,
                                text=True,
                                timeout=5,
                            )
                            if proc_result.returncode == 0 and proc_result.stdout:
                                proc_parts = proc_result.stdout.strip().split(",")
                                if len(proc_parts) >= 1:
                                    proc_name = proc_parts[0].strip('"')
                                    return (pid, proc_name)
            
        elif system == "Darwin":  # macOS
            # macOS: use lsof
            result = subprocess.run(
                ["lsof", "-i", f":{port}", "-P", "-n"],
                capture_output=True,
                text=True,
                timeout=10,
            )
            if result.returncode == 0 and result.stdout:
                # Parse lsof output
                lines = result.stdout.strip().split("\n")
                if len(lines) > 1:  # Skip header
                    for line in lines[1:]:
                        parts = line.split()
                        if len(parts) >= 2:
                            proc_name = parts[0]
                            pid_str = parts[1]
                            if pid_str.isdigit():
                                return (int(pid_str), proc_name)
        
        else:  # Linux
            # Linux: use ss or netstat
            # Try ss first (modern replacement for netstat)
            result = subprocess.run(
                ["ss", "-tlnp", f"sport = :{port}"],
                capture_output=True,
                text=True,
                timeout=10,
            )
            if result.returncode == 0 and result.stdout:
                # Parse ss output
                for line in result.stdout.split("\n"):
                    if f":{port}" in line:
                        # Look for pid/process in the line
                        if "users:" in line:
                            import re
                            match = re.search(r'pid=(\d+)', line)
                            if match:
                                pid = int(match.group(1))
                                # Extract process name
                                proc_match = re.search(r'"([^"]+)"', line)
                                proc_name = proc_match.group(1) if proc_match else "unknown"
                                return (pid, proc_name)
            
            # Fallback to netstat
            result = subprocess.run(
                ["netstat", "-tlnp"],
                capture_output=True,
                text=True,
                timeout=10,
            )
            if result.returncode == 0 and result.stdout:
                for line in result.stdout.split("\n"):
                    if f":{port}" in line:
                        parts = line.split()
                        if len(parts) >= 7:
                            # Format: proto recv-q send-q local foreign state pid/program
                            pid_prog = parts[-1]
                            if "/" in pid_prog:
                                pid_str, proc_name = pid_prog.split("/", 1)
                                if pid_str.isdigit():
                                    return (int(pid_str), proc_name)
    
    except Exception:
        pass
    
    return None


def kill_process(pid: int) -> bool:
    """
    Kill a process by PID (cross-platform).
    
    Args:
        pid: Process ID to kill
    
    Returns:
        True if successful, False otherwise
    """
    system = platform.system()
    
    try:
        if system == "Windows":
            subprocess.run(
                ["taskkill", "/F", "/PID", str(pid)],
                capture_output=True,
                check=True,
                timeout=10,
            )
        else:
            # Unix (Linux/macOS)
            import signal
            os.kill(pid, signal.SIGTERM)
            # Give it a moment to terminate gracefully
            time.sleep(1)
            # Check if still running
            try:
                os.kill(pid, 0)  # Check if process exists
                # Still running, force kill
                os.kill(pid, signal.SIGKILL)
            except ProcessLookupError:
                pass  # Already terminated
        
        return True
    except Exception:
        return False


def resolve_port_conflict(port: int = 18789, force: bool = False) -> tuple[bool, str]:
    """
    Check for and resolve port conflicts.
    
    Args:
        port: Port to check
        force: If True, kill conflicting processes
    
    Returns:
        tuple: (resolved, message)
    """
    proc_info = find_process_using_port(port)
    
    if not proc_info:
        return (True, f"Port {port} is available")
    
    pid, proc_name = proc_info
    
    if not force:
        return (False, f"Port {port} is in use by {proc_name} (PID: {pid})")
    
    # Try to kill the process
    print(f"   [INFO] Port {port} is in use by {proc_name} (PID: {pid})")
    print(f"   [INFO] Attempting to terminate process...")
    
    if kill_process(pid):
        # Wait a moment for port to be released
        time.sleep(2)
        # Verify port is now free
        if not find_process_using_port(port):
            return (True, f"Process {proc_name} (PID: {pid}) terminated, port {port} is now available")
        else:
            return (False, f"Process terminated but port {port} is still in use")
    else:
        return (False, f"Failed to terminate process {proc_name} (PID: {pid})")


def check_gateway_status(wrapper: Path, timeout: int = 30) -> tuple[bool, str]:
    """
    Check if the OpenClaw gateway is running and healthy.
    
    Returns:
        tuple: (is_healthy, status_message)
        - is_healthy: True if gateway is responding properly
        - status_message: Description of the status for debugging
    
    The status output can show various states:
    - "RPC probe: ok" - Service is healthy (best indicator)
    - "running" - Explicitly running
    - "Listening: 127.0.0.1:18789" - Port is open
    - "RPC probe: failed" - Service crashed (needs restart)
    """
    try:
        env = get_env_with_node()
        result = subprocess.run(
            [str(wrapper), "gateway", "status"],
            capture_output=True,
            text=True,
            timeout=timeout,
            env=env,
        )
        
        if result.returncode != 0:
            return False, "status command failed"
        
        output_lower = result.stdout.lower()
        output = result.stdout
        
        # Check for RPC probe failure first (gateway crashed)
        if "rpc probe: failed" in output_lower:
            return False, "RPC probe failed - gateway may have crashed"
        
        # Check for abnormal closure (WebSocket error)
        if "abnormal closure" in output_lower or "1006" in output_lower:
            return False, "WebSocket abnormal closure - gateway crashed"
        
        # Best indicator: RPC probe is OK
        if "rpc probe: ok" in output_lower:
            return True, "RPC probe OK"
        
        # Other positive indicators
        if "running" in output_lower:
            return True, "gateway running"
        if "listening:" in output_lower:
            return True, "port listening"
        if "state ready" in output_lower:
            return True, "state ready"
        if "dashboard: http://" in output_lower:
            return True, "dashboard URL available"
        
        return False, "unknown status"
        
    except subprocess.TimeoutExpired:
        return False, "status check timed out"
    except Exception as e:
        return False, f"status check error: {e}"


def start_gateway_service(
    wrapper: Path, 
    timeout: int = 30, 
    max_retries: int = 3,
    port: int = 18789,
    force_kill_conflicts: bool = True
) -> bool:
    """
    Try to start the gateway as a service (platform-specific).
    Retries multiple times to account for startup delay.
    
    Args:
        wrapper: Path to openclaw wrapper
        timeout: Timeout for subprocess calls
        max_retries: Number of retry attempts
        port: Port to use for gateway
        force_kill_conflicts: If True, kill processes using the port
    """
    print(f"[START] Starting OpenClaw gateway service...")
    
    # Check and resolve port conflicts
    if force_kill_conflicts:
        resolved, msg = resolve_port_conflict(port, force=True)
        if resolved:
            print(f"   [OK] {msg}")
        else:
            print(f"   [WARNING] {msg}")
            print(f"   [WARNING] Attempting to start anyway...")
    
    try:
        env = get_env_with_node()
        # Try service start first
        result = subprocess.run(
            [str(wrapper), "gateway", "start"],
            capture_output=True,
            text=True,
            timeout=timeout,
            env=env,
        )
        
        # Retry checking status multiple times with increasing delays
        # Gateway can take longer on slower devices (e.g., ARM boards like Jetson)
        for attempt in range(max_retries):
            wait_time = 5 + (attempt * 3)  # 5s, 8s, 11s - longer for slow devices
            print(f"   Waiting {wait_time}s for gateway to initialize (attempt {attempt + 1}/{max_retries})...")
            time.sleep(wait_time)
            
            is_ready, status_msg = check_gateway_status(wrapper)
            if is_ready:
                print(f"[OK] Gateway service started successfully ({status_msg})")
                return True
        
        print(f"[WARNING] Service start command executed, but gateway not responding: {status_msg}")
        return False
            
    except subprocess.TimeoutExpired:
        print("[WARNING] Gateway start timed out")
        return False
    except Exception as e:
        print(f"[WARNING] Failed to start gateway service: {e}")
        return False


def start_gateway_direct(
    wrapper: Path,
    port: int = 18789,
    max_retries: int = 3,
    force_kill_conflicts: bool = True
) -> Optional[subprocess.Popen]:
    """
    Start the gateway using direct Node.js command.
    This is more reliable than using the wrapper.
    
    Args:
        wrapper: Path to openclaw wrapper (for status checking)
        port: Port to use for gateway
        max_retries: Number of retry attempts
        force_kill_conflicts: If True, kill processes using the port
    
    Returns:
        subprocess.Popen if successful, None otherwise
    """
    print("[START] Starting gateway using direct Node.js command...")
    
    # Get paths
    node = get_node_path()
    index = get_openclaw_index_path()
    
    if not node:
        print("   [ERROR] Node.js not found")
        return None
    
    if not index:
        print("   [ERROR] OpenClaw index.js not found")
        return None
    
    print(f"   [INFO] Node: {node}")
    print(f"   [INFO] Index: {index}")
    
    # Check and resolve port conflicts
    if force_kill_conflicts:
        resolved, msg = resolve_port_conflict(port, force=True)
        if resolved:
            print(f"   [OK] {msg}")
        else:
            print(f"   [WARNING] {msg}")
            print(f"   [WARNING] Attempting to start anyway...")
    
    try:
        system = platform.system()
        
        # Build command: node index.js gateway --port 18789
        cmd = [str(node), str(index), "gateway", "--port", str(port)]
        
        if system == "Windows":
            # Windows: Use CREATE_NEW_PROCESS_GROUP
            process = subprocess.Popen(
                cmd,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                creationflags=subprocess.CREATE_NEW_PROCESS_GROUP,
            )
        else:
            # Unix (Linux/macOS): Use start_new_session
            process = subprocess.Popen(
                cmd,
                stdout=subprocess.DEVNULL,
                stderr=subprocess.DEVNULL,
                start_new_session=True,
            )
        
        # Retry checking status multiple times
        for attempt in range(max_retries):
            wait_time = 5 + (attempt * 3)  # 5s, 8s, 11s - longer for slow devices
            print(f"   Waiting {wait_time}s for gateway to initialize (attempt {attempt + 1}/{max_retries})...")
            time.sleep(wait_time)
            
            is_ready, status_msg = check_gateway_status(wrapper)
            if is_ready:
                print(f"[OK] Gateway is now running in background ({status_msg})")
                return process
        
        print(f"[WARNING] Gateway may still be starting ({status_msg})...")
        return process
        
    except Exception as e:
        print(f"[ERROR] Failed to start gateway in background: {e}")
        return None


def get_tokenized_url(wrapper: Path, timeout: int = 15) -> Optional[str]:
    """
    Get the tokenized dashboard URL from openclaw.
    This follows step 2 of the "How to connect" instructions.
    """
    try:
        print("[START] Getting authenticated dashboard URL...")
        env = get_env_with_node()
        result = subprocess.run(
            [str(wrapper), "dashboard", "--no-open"],
            capture_output=True,
            text=True,
            timeout=timeout,
            env=env,
        )
        
        # Parse stdout for URL
        output = result.stdout.strip()
        for line in output.split("\n"):
            if "http://" in line or "https://" in line:
                for word in line.split():
                    if word.startswith("http://") or word.startswith("https://"):
                        return word.strip()
        
        # Check if entire output is a URL
        if output.startswith("http://") or output.startswith("https://"):
            return output
        
        # Parse stderr as fallback
        if result.stderr:
            for line in result.stderr.split("\n"):
                if "http://" in line or "https://" in line:
                    for word in line.split():
                        if word.startswith("http://") or word.startswith("https://"):
                            return word.strip()
        
        return None
        
    except subprocess.TimeoutExpired:
        print("[WARNING] Getting URL timed out")
        return None
    except Exception as e:
        print(f"[ERROR] Failed to get tokenized URL: {e}")
        return None


def open_browser(url: str, browser_path: Optional[str] = None) -> bool:
    """
    Open the URL in a browser.
    Platform-specific browser handling.
    """
    print(f"[START] Opening dashboard...")
    
    try:
        # If specific browser path provided, use it
        if browser_path and Path(browser_path).exists():
            subprocess.Popen([browser_path, url], 
                           stdout=subprocess.DEVNULL, 
                           stderr=subprocess.DEVNULL)
            return True
        
        system = platform.system()
        
        if system == "Windows":
            # Windows: Use webbrowser module (uses default browser)
            webbrowser.open(url)
            
        elif system == "Darwin":  # macOS
            # macOS: Use 'open' command
            subprocess.run(["open", url], check=True)
            
        else:  # Linux
            # Linux: Try xdg-open first, then fall back to webbrowser
            try:
                subprocess.run(["xdg-open", url], check=True, 
                             capture_output=True, timeout=10)
            except (subprocess.CalledProcessError, FileNotFoundError):
                # Fall back to webbrowser module
                webbrowser.open(url)
        
        return True
        
    except Exception as e:
        print(f"[ERROR] Failed to open browser: {e}")
        print(f"   Please manually open: {url}")
        return False


def wait_for_gateway(wrapper: Path, max_wait: int = 30, interval: int = 2) -> tuple[bool, str]:
    """
    Wait for gateway to become ready with periodic checks.
    
    Args:
        wrapper: Path to openclaw wrapper
        max_wait: Maximum seconds to wait
        interval: Seconds between checks
    
    Returns:
        tuple: (is_ready, status_message)
    """
    print(f"   Waiting up to {max_wait}s for gateway to be ready...")
    
    elapsed = 0
    while elapsed < max_wait:
        is_ready, message = check_gateway_status(wrapper)
        if is_ready:
            return True, message
        time.sleep(interval)
        elapsed += interval
        if elapsed % 5 == 0:  # Print progress every 5 seconds
            print(f"   ... waited {elapsed}s (status: {message})")
    
    is_ready, message = check_gateway_status(wrapper)
    return False, f"timeout - {message}"


def get_env_with_node() -> dict:
    """Get environment with bundled Node.js in PATH."""
    env = os.environ.copy()
    
    # Add bundled node paths to PATH
    install_base = get_install_base()
    node_bin = install_base / "node" / "bin"
    if platform.system() == "Windows":
        node_bin = install_base / "node"
    
    # Add npm global bin
    npm_bin = get_npm_global_bin_dir()
    
    # Build new PATH
    new_path_parts = []
    if node_bin.exists():
        new_path_parts.append(str(node_bin))
    if npm_bin and npm_bin.exists():
        new_path_parts.append(str(npm_bin))
    new_path_parts.append(env.get("PATH", ""))
    
    env["PATH"] = os.pathsep.join(new_path_parts)
    return env


def auto_login(
    browser_path: Optional[str] = None,
    startup_timeout: int = 30,
    verbose: bool = False
) -> bool:
    """
    Perform zero-interaction login to OpenClaw dashboard.
    
    This follows the "How to connect" steps from the dashboard:
    1. Start the gateway on your host machine (openclaw gateway run)
    2. Get a tokenized dashboard URL (openclaw dashboard --no-open)
    3. Open the browser with the authenticated URL
    
    Args:
        browser_path: Optional path to specific browser executable
        startup_timeout: Seconds to wait for gateway startup
        verbose: Show detailed output
    
    Returns:
        True if successful, False otherwise
    """
    platform_name = get_platform_name()
    
    print("=" * 60)
    print(f"OpenClaw Auto-Login ({platform_name})")
    print("Following the 'How to connect' steps...")
    print("=" * 60)
    
    # Find wrapper
    wrapper = get_wrapper_path()
    if not wrapper:
        print(f"[FAIL] OpenClaw not found")
        print("   Detected platform:", platform_name)
        print("   Searched locations:")
        
        npm_bin = get_npm_global_bin_dir()
        if npm_bin:
            print(f"     - {npm_bin / 'openclaw'}")
        bundled_bin = get_bundled_node_bin()
        if bundled_bin:
            print(f"     - {bundled_bin / 'openclaw'}")
        print(f"     - PATH lookup for 'openclaw'")
        
        print("\n   Please run: openclaw-installer install")
        return False
    
    print(f"Using wrapper: {wrapper}")
    
    # Step 1: Ensure gateway is running
    print("\nStep 1: Checking gateway status...")
    gateway_process = None
    
    # Check with retry - gateway might be starting up
    is_ready, status_msg = check_gateway_status(wrapper)
    if is_ready:
        print(f"[OK] Gateway is already running ({status_msg})")
    else:
        print(f"Gateway status: {status_msg}")
        print("Attempting to start gateway...")
        
        # Try service start first (using wrapper)
        if start_gateway_service(wrapper, timeout=startup_timeout):
            # Wait for it to be ready
            is_ready, status_msg = wait_for_gateway(wrapper, max_wait=startup_timeout, interval=2)
        
        # If service start didn't work, try direct Node.js
        if not is_ready:
            print("\nService start had issues, trying direct Node.js command...")
            gateway_process = start_gateway_direct(wrapper, port=18789)
            
            if not gateway_process:
                print("[FAIL] Failed to start gateway")
                return False
            
            # Wait for direct start to be ready
            is_ready, status_msg = wait_for_gateway(wrapper, max_wait=startup_timeout, interval=2)
        
        # Final check - if still not ready, fail
        if not is_ready:
            print(f"[FAIL] Gateway failed to start: {status_msg}")
            print("\nTroubleshooting:")
            print("  1. Check if port 18789 is in use: lsof -i :18789")
            print("  2. Try running manually: openclaw gateway run")
            print("  3. Check logs: openclaw logs")
            return False
        
        print(f"[OK] Gateway is now running ({status_msg})")
    
    # Step 2: Verify gateway is really working before opening browser
    print("\nStep 2: Verifying gateway is healthy...")
    is_ready, status_msg = check_gateway_status(wrapper)
    if not is_ready:
        print(f"[FAIL] Gateway not responding: {status_msg}")
        return False
    
    print(f"[OK] Gateway verified ({status_msg})")
    
    # Step 3: Get tokenized URL
    print("\nStep 3: Getting authenticated dashboard URL...")
    dashboard_url = get_tokenized_url(wrapper)
    
    if not dashboard_url:
        print("[WARNING] Could not get tokenized URL, using default...")
        port = 18789  # Default port
        dashboard_url = f"http://127.0.0.1:{port}/"
    else:
        print("[OK] Got authenticated URL")
        if verbose:
            print(f"   URL: {dashboard_url[:60]}...")
    
    # Step 4: Open browser (only after gateway is confirmed working)
    print("\nStep 4: Opening dashboard in browser...")
    
    if open_browser(dashboard_url, browser_path):
        print("\n" + "=" * 60)
        print("[SUCCESS] Dashboard is now open in your browser.")
        print("=" * 60)
        print("\nThe dashboard is now logged in automatically.")
        print("No manual token entry needed!")
        
        if gateway_process:
            print("\n[NOTE] Gateway is running in foreground mode.")
            print("Keep this terminal open to maintain the connection.")
        
        print("\n[TIP] If dashboard shows connection issues, run:")
        print("   openclaw gateway status")
        print("   openclaw gateway restart")
        
        return True
    else:
        print("\n" + "=" * 60)
        print(f"[WARNING] Could not open browser automatically.")
        print(f"Please manually open: {dashboard_url}")
        print("=" * 60)
        return False


def main():
    """Main entry point for command-line usage."""
    import argparse
    
    parser = argparse.ArgumentParser(
        description="OpenClaw Auto-Login - Zero-interaction dashboard access"
    )
    parser.add_argument(
        "--browser", "-b",
        help="Path to browser executable (optional)"
    )
    parser.add_argument(
        "--timeout", "-t",
        type=int,
        default=30,
        help="Timeout for gateway startup (seconds)"
    )
    parser.add_argument(
        "--verbose", "-v",
        action="store_true",
        help="Show detailed output"
    )
    
    args = parser.parse_args()
    
    try:
        success = auto_login(
            browser_path=args.browser,
            startup_timeout=args.timeout,
            verbose=args.verbose
        )
        sys.exit(0 if success else 1)
        
    except KeyboardInterrupt:
        print("\n\n[WARNING] Interrupted by user")
        sys.exit(130)
    except Exception as e:
        print(f"\n[ERROR] Unexpected error: {e}")
        if args.verbose:
            import traceback
            traceback.print_exc()
        sys.exit(1)


if __name__ == "__main__":
    main()
