"""
Server management utilities for Universal MCP Client
Version 2.0 - Enhanced with server enabling/disabling support
"""
import asyncio
import re
import logging
import traceback
from typing import Tuple
from config import MCPServerConfig
from mcp_client import UniversalMCPClient
logger = logging.getLogger(__name__)
class ServerManager:
    """Manages MCP server connections and status with enhanced server management"""
    
    def __init__(self, mcp_client: UniversalMCPClient):
        self.mcp_client = mcp_client
    
    def convert_hf_space_to_url(self, space_name: str) -> str:
        """
        Convert HuggingFace space name to proper URL format.
        
        HuggingFace URL rules:
        - Replace "/" with "-" 
        - Convert to lowercase
        - Replace dots and other special chars with "-"
        - Remove consecutive hyphens
        """
        if "/" not in space_name:
            raise ValueError("Space name should be in format: username/space-name")
        
        # Replace "/" with "-"
        url_name = space_name.replace("/", "-")
        
        # Convert to lowercase
        url_name = url_name.lower()
        
        # Replace dots and other special characters with hyphens
        url_name = re.sub(r'[^a-z0-9\-]', '-', url_name)
        
        # Remove consecutive hyphens
        url_name = re.sub(r'-+', '-', url_name)
        
        # Remove leading/trailing hyphens
        url_name = url_name.strip('-')
        
        return f"https://{url_name}.hf.space"
    
    def add_custom_server(self, name: str, space_name: str) -> Tuple[str, str]:
        """Add a custom MCP server from HuggingFace space name"""
        logger.info(f"â Adding MCP server: {name} from space: {space_name}")
        
        if not name or not space_name:
            return "â Please provide both server name and space name", ""
        
        space_name = space_name.strip()
        
        try:
            # Use the improved URL conversion
            mcp_url = self.convert_hf_space_to_url(space_name)
            logger.info(f"đ Converted {space_name} â {mcp_url}")
            
        except ValueError as e:
            return f"â {str(e)}", ""
        
        config = MCPServerConfig(
            name=name.strip(), 
            url=mcp_url, 
            description=f"MCP server from HuggingFace space: {space_name}",
            space_id=space_name
        )
        
        try:
            # Run async function
            def run_async():
                loop = asyncio.new_event_loop()
                asyncio.set_event_loop(loop)
                try:
                    return loop.run_until_complete(self.mcp_client.add_server_async(config))
                finally:
                    loop.close()
            
            success, message = run_async()
            logger.info(f"Server addition result: {success} - {message}")
            
            if success:
                # Format success message for accordion display
                tools_info = ""
                if 'Found' in message and 'tools:' in message:
                    tools_section = message.split('Found')[1]
                    tools_info = f"**Available Tools:**\n{tools_section}"
                
                details_html = f"""
                 Space: {space_name} Base URL: {mcp_url} Status: Connected successfully! Enabled: Yes (new servers are enabled by default) {message}â
 {name} - Connection Details
                    
')}
                        â {name} - Connection Failed
                    
No MCP servers configured yet.
" accordion_html = "" for name, config in self.mcp_client.servers.items(): logger.info(f"đ Processing server: {name}") base_url = config.url.replace("/gradio_api/mcp/sse", "") # Determine health status (assume healthy if it's in the servers dict) health = "đĸ Healthy" accordion_html += f"""Title: {name}
Status: Connected (MCP Protocol)
Health: {health}
Base URL: {base_url}
Description: {config.description}
{f'Space ID: {config.space_id}
' if config.space_id else ''}â {error_msg}
" def remove_server(self, server_name: str) -> Tuple[str, str]: """Remove a specific server""" success = self.mcp_client.remove_server(server_name) if success: return f"â Removed server: {server_name}", "" else: return f"â Server not found: {server_name}", "" def remove_all_servers(self) -> Tuple[str, str]: """Remove all servers""" count = self.mcp_client.remove_all_servers() if count > 0: return f"â Removed all {count} MCP servers", "" else: return "âšī¸ No servers to remove", "" def enable_server(self, server_name: str, enabled: bool = True) -> Tuple[str, str]: """Enable or disable a server""" if server_name in self.mcp_client.servers: self.mcp_client.enable_server(server_name, enabled) status = "enabled" if enabled else "disabled" return f"â Server {server_name} {status}", "" else: return f"â Server not found: {server_name}", "" def get_server_list_with_status(self) -> list: """Get server list with enable/disable status for UI components""" return self.mcp_client.get_server_list_with_status()