"""
NC1709 CLI - Main Command Line Interface
Provides both direct command mode and interactive shell mode
"""
import sys
import argparse
from pathlib import Path
from typing import Optional

from .config import get_config
from .llm_adapter import LLMAdapter, TaskType, TaskClassifier
from .file_controller import FileController
from .executor import CommandExecutor
from .reasoning_engine import ReasoningEngine


class NC1709CLI:
    """Main CLI application"""

    def __init__(self):
        """Initialize the CLI"""
        self.config = get_config()
        self.llm = LLMAdapter()
        self.file_controller = FileController()
        self.executor = CommandExecutor()
        self.reasoning_engine = ReasoningEngine()
        self.running = True

        # Memory module (lazy loaded)
        self._session_manager = None
        self._project_indexer = None
        self._memory_enabled = self.config.get("memory.enabled", False)

        # Plugin system (lazy loaded)
        self._plugin_manager = None

        # MCP support (lazy loaded)
        self._mcp_manager = None

    @property
    def session_manager(self):
        """Lazy load session manager"""
        if self._session_manager is None:
            try:
                from .memory.sessions import SessionManager
                self._session_manager = SessionManager()
            except ImportError:
                pass
        return self._session_manager

    @property
    def project_indexer(self):
        """Lazy load project indexer"""
        if self._project_indexer is None and self._memory_enabled:
            try:
                from .memory.indexer import ProjectIndexer
                self._project_indexer = ProjectIndexer(str(Path.cwd()))
            except ImportError:
                pass
        return self._project_indexer

    @property
    def plugin_manager(self):
        """Lazy load plugin manager"""
        if self._plugin_manager is None:
            try:
                from .plugins import PluginManager
                self._plugin_manager = PluginManager()
                # Discover and load built-in plugins
                self._plugin_manager.discover_plugins()
                self._plugin_manager.load_all()
            except ImportError:
                pass
        return self._plugin_manager

    @property
    def mcp_manager(self):
        """Lazy load MCP manager"""
        if self._mcp_manager is None:
            try:
                from .mcp import MCPManager
                self._mcp_manager = MCPManager(name="nc1709", version="1.0.0")
                self._mcp_manager.setup_default_tools()
            except ImportError:
                pass
        return self._mcp_manager

    def run(self, args: Optional[list] = None) -> int:
        """Run the CLI

        Args:
            args: Command line arguments (default: sys.argv)

        Returns:
            Exit code
        """
        parser = self._create_parser()
        parsed_args = parser.parse_args(args)

        # Handle different modes
        if parsed_args.version:
            self._print_version()
            return 0

        if parsed_args.config:
            self._show_config()
            return 0

        # Session management
        if parsed_args.sessions:
            return self._list_sessions()

        if parsed_args.resume:
            return self._run_shell(resume_session=parsed_args.resume)

        # Project indexing
        if parsed_args.index:
            return self._index_project()

        if parsed_args.search:
            return self._search_code(parsed_args.search)

        # Plugin commands
        if parsed_args.plugins:
            return self._list_plugins()

        if parsed_args.plugin:
            return self._run_plugin_action(parsed_args.plugin)

        # MCP commands
        if parsed_args.mcp_status:
            return self._mcp_show_status()

        if parsed_args.mcp_serve:
            return self._mcp_run_server()

        if parsed_args.mcp_connect:
            return self._mcp_connect_servers(parsed_args.mcp_connect)

        if parsed_args.mcp_tool:
            args_json = parsed_args.args if parsed_args.args else "{}"
            return self._mcp_call_tool(parsed_args.mcp_tool, args_json)

        # Web dashboard
        if parsed_args.web:
            return self._run_web_dashboard(parsed_args.port)

        if parsed_args.shell or not parsed_args.prompt:
            # Interactive shell mode
            return self._run_shell()
        else:
            # Direct command mode
            return self._run_command(parsed_args.prompt)
    
    def _create_parser(self) -> argparse.ArgumentParser:
        """Create argument parser
        
        Returns:
            Argument parser
        """
        parser = argparse.ArgumentParser(
            prog="nc1709",
            description="NC1709 - A Local-First AI Developer Assistant",
            epilog="Examples:\n"
                   "  nc1709 'create a Python script to parse JSON'\n"
                   "  nc1709 --shell\n"
                   "  nc1709 --config",
            formatter_class=argparse.RawDescriptionHelpFormatter
        )
        
        parser.add_argument(
            "prompt",
            nargs="?",
            help="Your request or question"
        )
        
        parser.add_argument(
            "-s", "--shell",
            action="store_true",
            help="Start interactive shell mode"
        )
        
        parser.add_argument(
            "-v", "--version",
            action="store_true",
            help="Show version information"
        )
        
        parser.add_argument(
            "-c", "--config",
            action="store_true",
            help="Show current configuration"
        )
        
        parser.add_argument(
            "--verbose",
            action="store_true",
            help="Enable verbose output"
        )

        # Session management arguments
        parser.add_argument(
            "--sessions",
            action="store_true",
            help="List saved sessions"
        )

        parser.add_argument(
            "--resume",
            metavar="SESSION_ID",
            help="Resume a previous session"
        )

        # Memory/indexing arguments
        parser.add_argument(
            "--index",
            action="store_true",
            help="Index the current project for semantic search"
        )

        parser.add_argument(
            "--search",
            metavar="QUERY",
            help="Search indexed code semantically"
        )

        # Plugin arguments
        parser.add_argument(
            "--plugins",
            action="store_true",
            help="List available plugins"
        )

        parser.add_argument(
            "--plugin",
            metavar="NAME",
            help="Execute a plugin action (e.g., --plugin git:status)"
        )

        # MCP arguments
        parser.add_argument(
            "--mcp-status",
            action="store_true",
            help="Show MCP server status and available tools"
        )

        parser.add_argument(
            "--mcp-serve",
            action="store_true",
            help="Run NC1709 as an MCP server (stdio transport)"
        )

        parser.add_argument(
            "--mcp-connect",
            metavar="CONFIG",
            help="Connect to MCP servers from config file"
        )

        parser.add_argument(
            "--mcp-tool",
            metavar="TOOL",
            help="Call an MCP tool (e.g., --mcp-tool read_file --args '{\"path\": \"file.txt\"}')"
        )

        parser.add_argument(
            "--args",
            metavar="JSON",
            help="JSON arguments for --mcp-tool"
        )

        # Web Dashboard arguments
        parser.add_argument(
            "--web",
            action="store_true",
            help="Start the web dashboard (default: http://localhost:8709)"
        )

        parser.add_argument(
            "--port",
            type=int,
            default=8709,
            help="Port for web dashboard (default: 8709)"
        )

        return parser
    
    def _print_version(self) -> None:
        """Print version information"""
        from . import __version__
        print(f"NC1709 CLI v{__version__}")
        print("A Local-First AI Developer Assistant")
        print("\nConfigured Models:")
        for task_type in TaskType:
            model_info = self.llm.get_model_info(task_type)
            print(f"  {task_type.value:12} → {model_info['model']}")
    
    def _show_config(self) -> None:
        """Show current configuration"""
        import json
        print("Current Configuration:")
        print(json.dumps(self.config.config, indent=2))
        print(f"\nConfig file: {self.config.config_path}")
    
    def _run_shell(self, resume_session: Optional[str] = None) -> int:
        """Run interactive shell mode

        Args:
            resume_session: Session ID to resume

        Returns:
            Exit code
        """
        self._print_banner()

        # Initialize or resume session
        if self.session_manager:
            if resume_session:
                session = self.session_manager.load_session(resume_session)
                if session:
                    self.session_manager.current_session = session
                    print(f"📂 Resumed session: {session.name} ({len(session.messages)} messages)")
                else:
                    print(f"⚠️  Session '{resume_session}' not found, starting new session")
                    self.session_manager.start_session(project_path=str(Path.cwd()))
            else:
                self.session_manager.start_session(project_path=str(Path.cwd()))
                print(f"📝 Started new session: {self.session_manager.current_session.id}")

        print("\nType 'help' for available commands, 'exit' to quit.\n")

        while self.running:
            try:
                # Get user input
                prompt = input("\n🤖 nc1709> ").strip()

                if not prompt:
                    continue

                # Handle special commands
                if prompt.lower() in ["exit", "quit", "q"]:
                    if self.session_manager and self.session_manager.current_session:
                        self.session_manager.save_session(self.session_manager.current_session)
                        print(f"💾 Session saved: {self.session_manager.current_session.id}")
                    print("Goodbye! 👋")
                    break

                if prompt.lower() == "help":
                    self._print_help()
                    continue

                if prompt.lower() == "clear":
                    self.llm.clear_history()
                    print("✅ Conversation history cleared")
                    continue

                if prompt.lower() == "history":
                    self._show_history()
                    continue

                if prompt.lower().startswith("config "):
                    self._handle_config_command(prompt)
                    continue

                # New memory commands
                if prompt.lower() == "sessions":
                    self._list_sessions()
                    continue

                if prompt.lower().startswith("search "):
                    query = prompt[7:].strip()
                    self._search_code(query)
                    continue

                if prompt.lower() == "index":
                    self._index_project()
                    continue

                # Plugin commands
                if prompt.lower() == "plugins":
                    self._list_plugins()
                    continue

                if prompt.lower().startswith("git "):
                    self._run_plugin_action(f"git:{prompt[4:].strip()}")
                    continue

                if prompt.lower().startswith("docker "):
                    self._run_plugin_action(f"docker:{prompt[7:].strip()}")
                    continue

                # MCP commands
                if prompt.lower() == "mcp":
                    self._mcp_show_status()
                    continue

                if prompt.lower() == "mcp tools":
                    self._mcp_list_tools()
                    continue

                if prompt.lower().startswith("mcp call "):
                    tool_spec = prompt[9:].strip()
                    self._mcp_call_tool_interactive(tool_spec)
                    continue

                # Process the request
                self._process_request(prompt)

            except KeyboardInterrupt:
                print("\n\nUse 'exit' to quit.")
                continue

            except Exception as e:
                print(f"\n❌ Error: {e}")
                if self.config.get("ui.verbose"):
                    import traceback
                    traceback.print_exc()

        return 0
    
    def _run_command(self, prompt: str) -> int:
        """Run a single command
        
        Args:
            prompt: User's prompt
        
        Returns:
            Exit code
        """
        try:
            self._process_request(prompt)
            return 0
        except Exception as e:
            print(f"❌ Error: {e}", file=sys.stderr)
            return 1
    
    def _process_request(self, prompt: str) -> None:
        """Process a user request
        
        Args:
            prompt: User's prompt
        """
        # Classify the task
        task_type = TaskClassifier.classify(prompt)
        
        # Get context
        context = {
            "cwd": str(Path.cwd()),
            "task_type": task_type.value
        }
        
        # Use reasoning engine for complex requests
        response = self.reasoning_engine.process_request(prompt, context)
        
        # Print response
        print(f"\n{response}")
    
    def _print_banner(self) -> None:
        """Print welcome banner"""
        from . import __version__
        banner = f"""
╔═══════════════════════════════════════════════════════════╗
║                                                           ║
║              NC1709 CLI v{__version__}                        ║
║       A Local-First AI Developer Assistant                ║
║                                                           ║
║  🔒 100% Local  •  🧠 Multi-Model  •  🚀 Powerful         ║
║                                                           ║
╚═══════════════════════════════════════════════════════════╝
"""
        print(banner)
    
    def _print_help(self) -> None:
        """Print help message"""
        help_text = """
Available Commands:

  help          Show this help message
  exit/quit     Exit the shell
  clear         Clear conversation history
  history       Show command execution history
  config        Show current configuration

Memory & Search:

  sessions      List saved conversation sessions
  index         Index current project for semantic search
  search <q>    Search indexed code (e.g., "search authentication logic")

Plugins:

  plugins       List available plugins
  git <cmd>     Git operations (status, diff, log, branch, commit, etc.)
  docker <cmd>  Docker operations (ps, images, logs, compose up/down, etc.)

MCP (Model Context Protocol):

  mcp           Show MCP status and info
  mcp tools     List all available MCP tools
  mcp call <t>  Call an MCP tool (e.g., "mcp call read_file path=main.py")

Examples:

  • "Read the file main.py and explain what it does"
  • "Create a Python script to fetch data from an API"
  • "git status" or "git diff"
  • "docker ps" or "docker compose up"
  • "search where is the database connection"

Tips:

  • Be specific about what you want
  • Mention file names when working with code
  • The assistant will ask for confirmation before making changes
  • Use Ctrl+C to cancel the current operation
  • Run 'plugins' to see all available plugins
"""
        print(help_text)
    
    def _show_history(self) -> None:
        """Show command execution history"""
        history = self.executor.get_execution_history(limit=20)
        
        if not history:
            print("No command history yet.")
            return
        
        print("\nRecent Command History:")
        print("="*60)
        
        for i, entry in enumerate(history, 1):
            status = "✅" if entry["success"] else "❌"
            print(f"{i}. {status} {entry['command']}")
            print(f"   Time: {entry['timestamp']}")
            print(f"   Exit code: {entry['return_code']}")
            print()
    
    def _handle_config_command(self, prompt: str) -> None:
        """Handle config commands
        
        Args:
            prompt: Config command
        """
        parts = prompt.split(maxsplit=2)
        
        if len(parts) < 2:
            self._show_config()
            return
        
        if parts[1] == "get":
            if len(parts) < 3:
                print("Usage: config get <key>")
                return
            key = parts[2]
            value = self.config.get(key)
            print(f"{key} = {value}")
        
        elif parts[1] == "set":
            if len(parts) < 3:
                print("Usage: config set <key> <value>")
                return
            # Parse key=value
            if "=" not in parts[2]:
                print("Usage: config set <key>=<value>")
                return
            key, value = parts[2].split("=", 1)
            self.config.set(key.strip(), value.strip())
            print(f"✅ Set {key} = {value}")
        
        else:
            print("Unknown config command. Use 'config get <key>' or 'config set <key>=<value>'")

    def _list_sessions(self) -> int:
        """List saved sessions

        Returns:
            Exit code
        """
        if not self.session_manager:
            print("⚠️  Session management not available")
            return 1

        sessions = self.session_manager.list_sessions(limit=20)

        if not sessions:
            print("No saved sessions found.")
            return 0

        print("\n📚 Saved Sessions:")
        print("=" * 70)

        for session in sessions:
            msg_count = session.get("message_count", 0)
            project = session.get("project_path", "N/A")
            if project and len(project) > 30:
                project = "..." + project[-27:]

            print(f"  ID: {session['id']}")
            print(f"  Name: {session['name']}")
            print(f"  Messages: {msg_count}")
            print(f"  Updated: {session.get('updated_at', 'N/A')[:19]}")
            print(f"  Project: {project}")
            print("-" * 70)

        print(f"\nTo resume a session: nc1709 --resume <session_id>")
        return 0

    def _index_project(self) -> int:
        """Index the current project for semantic search

        Returns:
            Exit code
        """
        try:
            from .memory.indexer import ProjectIndexer

            print(f"🔍 Indexing project: {Path.cwd()}")
            print("This may take a few minutes for large projects...\n")

            indexer = ProjectIndexer(str(Path.cwd()))
            stats = indexer.index_project(show_progress=True)

            print(f"\n✅ Indexing complete!")
            print(f"   Files indexed: {stats['files_indexed']}")
            print(f"   Total chunks: {stats['chunks_created']}")

            if stats['errors']:
                print(f"   Errors: {len(stats['errors'])}")

            return 0

        except ImportError:
            print("⚠️  Memory module dependencies not installed.")
            print("   Install with: pip install chromadb sentence-transformers")
            return 1
        except Exception as e:
            print(f"❌ Error indexing project: {e}")
            return 1

    def _search_code(self, query: str) -> int:
        """Search indexed code

        Args:
            query: Search query

        Returns:
            Exit code
        """
        if not query:
            print("Usage: search <query>")
            return 1

        try:
            from .memory.indexer import ProjectIndexer

            indexer = ProjectIndexer(str(Path.cwd()))

            # Check if project is indexed
            summary = indexer.get_project_summary()
            if summary['total_files'] == 0:
                print("⚠️  Project not indexed yet. Run 'index' first.")
                return 1

            print(f"\n🔍 Searching for: {query}\n")

            results = indexer.search(query, n_results=5)

            if not results:
                print("No results found.")
                return 0

            print(f"Found {len(results)} results:\n")
            print("=" * 70)

            for i, result in enumerate(results, 1):
                similarity = result.get('similarity', 0) * 100
                location = result.get('location', 'Unknown')
                language = result.get('language', 'unknown')

                print(f"\n📄 Result {i} ({similarity:.1f}% match)")
                print(f"   Location: {location}")
                print(f"   Language: {language}")
                print("-" * 70)

                # Show code preview (first 10 lines)
                code = result.get('content', '')
                lines = code.split('\n')[:10]
                for line in lines:
                    print(f"   {line[:80]}")
                if len(code.split('\n')) > 10:
                    print("   ...")

            print("\n" + "=" * 70)
            return 0

        except ImportError:
            print("⚠️  Memory module dependencies not installed.")
            print("   Install with: pip install chromadb sentence-transformers")
            return 1
        except Exception as e:
            print(f"❌ Error searching: {e}")
            return 1

    def _list_plugins(self) -> int:
        """List available plugins

        Returns:
            Exit code
        """
        if not self.plugin_manager:
            print("⚠️  Plugin system not available")
            return 1

        status = self.plugin_manager.get_status()

        if not status:
            print("No plugins registered.")
            return 0

        print("\n🔌 Available Plugins:")
        print("=" * 70)

        for name, info in status.items():
            status_icon = "✅" if info["status"] == "active" else "❌"
            builtin_tag = " [built-in]" if info.get("builtin") else ""

            print(f"\n  {status_icon} {name} v{info['version']}{builtin_tag}")
            print(f"      Status: {info['status']}")

            if info.get("error"):
                print(f"      Error: {info['error']}")

            # Show actions for loaded plugins
            plugin = self.plugin_manager.get_plugin(name)
            if plugin and plugin.actions:
                actions = ", ".join(plugin.actions.keys())
                print(f"      Actions: {actions}")

        print("\n" + "=" * 70)
        print("\nUsage: nc1709 --plugin <name>:<action>")
        print("Example: nc1709 --plugin git:status")
        return 0

    def _run_plugin_action(self, action_spec: str) -> int:
        """Run a plugin action

        Args:
            action_spec: Plugin:action specification (e.g., "git:status")

        Returns:
            Exit code
        """
        if not self.plugin_manager:
            print("⚠️  Plugin system not available")
            return 1

        # Parse action spec
        if ":" not in action_spec:
            # Try to find a plugin that can handle this as a request
            handlers = self.plugin_manager.find_handler(action_spec)
            if handlers:
                plugin_name = handlers[0][0]
                plugin = self.plugin_manager.get_plugin(plugin_name)
                if plugin and hasattr(plugin, 'handle_request'):
                    result = plugin.handle_request(action_spec)
                    if result:
                        self._print_action_result(result)
                        return 0 if result.success else 1

            print(f"❌ Invalid format. Use: <plugin>:<action>")
            print(f"   Example: git:status, docker:ps")
            return 1

        parts = action_spec.split(":", 1)
        plugin_name = parts[0].strip()
        action_name = parts[1].strip() if len(parts) > 1 else ""

        # Get the plugin
        plugin = self.plugin_manager.get_plugin(plugin_name)
        if not plugin:
            # Try to load it
            if not self.plugin_manager.load_plugin(plugin_name):
                print(f"❌ Plugin '{plugin_name}' not found")
                return 1
            plugin = self.plugin_manager.get_plugin(plugin_name)

        # If no action specified, show plugin help
        if not action_name:
            print(plugin.get_help())
            return 0

        # Check if action exists
        if action_name not in plugin.actions:
            # Try to handle as natural language
            if hasattr(plugin, 'handle_request'):
                result = plugin.handle_request(action_name)
                if result:
                    self._print_action_result(result)
                    return 0 if result.success else 1

            print(f"❌ Unknown action: {action_name}")
            print(f"   Available actions: {', '.join(plugin.actions.keys())}")
            return 1

        # Execute the action
        result = self.plugin_manager.execute_action(plugin_name, action_name)
        self._print_action_result(result)
        return 0 if result.success else 1

    def _print_action_result(self, result) -> None:
        """Print an action result

        Args:
            result: ActionResult to print
        """
        if result.success:
            print(f"\n✅ {result.message}")
        else:
            print(f"\n❌ {result.message}")
            if result.error:
                print(f"   Error: {result.error}")

        # Print data if present
        if result.data:
            if isinstance(result.data, str):
                print(f"\n{result.data}")
            elif isinstance(result.data, list):
                for item in result.data:
                    if hasattr(item, '__dict__'):
                        # Dataclass or object
                        print(f"  - {item}")
                    else:
                        print(f"  - {item}")
            elif hasattr(result.data, '__dict__'):
                # Single object
                for key, value in vars(result.data).items():
                    if not key.startswith('_'):
                        print(f"  {key}: {value}")

    # =========================================================================
    # MCP Methods
    # =========================================================================

    def _mcp_show_status(self) -> int:
        """Show MCP status

        Returns:
            Exit code
        """
        if not self.mcp_manager:
            print("⚠️  MCP module not available")
            return 1

        status = self.mcp_manager.get_status()

        print("\n🔌 MCP Status:")
        print("=" * 60)

        # Server info
        server = status["server"]
        print(f"\n📡 Local Server: {server['name']} v{server['version']}")
        print(f"   Running: {'Yes' if server['running'] else 'No'}")
        print(f"   Tools: {server['tools']}")
        print(f"   Resources: {server['resources']}")
        print(f"   Prompts: {server['prompts']}")

        # Connected servers
        client = status["client"]
        print(f"\n🌐 Connected Servers: {client['connected_servers']}")

        if client["servers"]:
            for srv in client["servers"]:
                status_icon = "✅" if srv["connected"] else "❌"
                print(f"   {status_icon} {srv['name']}: {srv['tools']} tools, {srv['resources']} resources")

        print("\n" + "=" * 60)
        print("\nCommands:")
        print("  mcp tools     - List available tools")
        print("  mcp call <t>  - Call a tool")
        print("  --mcp-serve   - Run as MCP server")
        return 0

    def _mcp_list_tools(self) -> int:
        """List MCP tools

        Returns:
            Exit code
        """
        if not self.mcp_manager:
            print("⚠️  MCP module not available")
            return 1

        all_tools = self.mcp_manager.get_all_tools()

        print("\n🔧 Available MCP Tools:")
        print("=" * 60)

        # Local tools
        if all_tools["local"]:
            print("\n📍 Local Tools:")
            for tool in all_tools["local"]:
                print(f"\n  {tool.name}")
                print(f"    Description: {tool.description}")
                if tool.parameters:
                    params = ", ".join(p.name for p in tool.parameters)
                    print(f"    Parameters: {params}")

        # Remote tools
        if all_tools["remote"]:
            print("\n🌐 Remote Tools:")
            for tool in all_tools["remote"]:
                print(f"\n  {tool.name}")
                print(f"    Description: {tool.description}")

        if not all_tools["local"] and not all_tools["remote"]:
            print("\nNo tools available.")

        print("\n" + "=" * 60)
        return 0

    def _mcp_call_tool_interactive(self, tool_spec: str) -> int:
        """Call an MCP tool from interactive mode

        Args:
            tool_spec: Tool name and args (e.g., "read_file path=main.py")

        Returns:
            Exit code
        """
        import json

        parts = tool_spec.split(maxsplit=1)
        tool_name = parts[0]
        args_str = parts[1] if len(parts) > 1 else ""

        # Parse key=value args
        args = {}
        if args_str:
            for pair in args_str.split():
                if "=" in pair:
                    key, value = pair.split("=", 1)
                    # Try to parse as JSON for complex values
                    try:
                        args[key] = json.loads(value)
                    except json.JSONDecodeError:
                        args[key] = value

        return self._mcp_call_tool(tool_name, json.dumps(args))

    def _mcp_call_tool(self, tool_name: str, args_json: str) -> int:
        """Call an MCP tool

        Args:
            tool_name: Tool name
            args_json: JSON string of arguments

        Returns:
            Exit code
        """
        import json
        import asyncio

        if not self.mcp_manager:
            print("⚠️  MCP module not available")
            return 1

        try:
            args = json.loads(args_json)
        except json.JSONDecodeError as e:
            print(f"❌ Invalid JSON arguments: {e}")
            return 1

        print(f"\n🔧 Calling tool: {tool_name}")
        if args:
            print(f"   Arguments: {args}")

        try:
            # Run async call
            result = asyncio.run(self.mcp_manager.call_tool(tool_name, args))

            if "error" in result:
                print(f"\n❌ Error: {result['error']}")
                return 1

            print("\n✅ Result:")
            print("-" * 40)

            if "content" in result:
                for item in result["content"]:
                    if item.get("type") == "text":
                        print(item.get("text", ""))
            else:
                print(json.dumps(result, indent=2))

            return 0

        except Exception as e:
            print(f"❌ Error calling tool: {e}")
            return 1

    def _mcp_run_server(self) -> int:
        """Run NC1709 as an MCP server

        Returns:
            Exit code (never returns normally)
        """
        import asyncio

        if not self.mcp_manager:
            print("⚠️  MCP module not available", file=sys.stderr)
            return 1

        # Don't print to stdout as it's used for MCP communication
        print("Starting NC1709 MCP server (stdio)...", file=sys.stderr)

        try:
            asyncio.run(self.mcp_manager.server.run_stdio())
        except KeyboardInterrupt:
            print("\nServer stopped.", file=sys.stderr)

        return 0

    def _mcp_connect_servers(self, config_path: str) -> int:
        """Connect to MCP servers from config

        Args:
            config_path: Path to MCP config file

        Returns:
            Exit code
        """
        import asyncio

        if not self.mcp_manager:
            print("⚠️  MCP module not available")
            return 1

        print(f"🔌 Connecting to MCP servers from: {config_path}")

        try:
            count = asyncio.run(self.mcp_manager.auto_discover_servers(config_path))

            if count > 0:
                print(f"\n✅ Connected to {count} server(s)")

                # Show connected servers
                servers = self.mcp_manager.list_connected_servers()
                for srv in servers:
                    print(f"   - {srv['name']}: {srv['tools']} tools")

                return 0
            else:
                print("\n⚠️  No servers connected. Check config file.")
                return 1

        except Exception as e:
            print(f"❌ Error connecting: {e}")
            return 1

    # =========================================================================
    # Web Dashboard Methods
    # =========================================================================

    def _run_web_dashboard(self, port: int = 8709) -> int:
        """Run the web dashboard

        Args:
            port: Port to run on

        Returns:
            Exit code
        """
        try:
            from .web import run_server
            run_server(host="127.0.0.1", port=port)
            return 0
        except ImportError as e:
            print("⚠️  Web dashboard dependencies not installed.")
            print("   Install with: pip install fastapi uvicorn")
            print(f"   Error: {e}")
            return 1
        except Exception as e:
            print(f"❌ Error starting web dashboard: {e}")
            return 1


def main():
    """Main entry point"""
    cli = NC1709CLI()
    sys.exit(cli.run())


if __name__ == "__main__":
    main()
