"""
SMF CLI - Command-line interface for SMF operations.

Provides commands for:
- Initializing projects
- Adding components
- Validating configuration
- Running servers
"""

import argparse
import json
import sys
from pathlib import Path
from typing import Any, Dict, Optional

from smf.settings import Settings


def write_utf8(file_path: Path, content: str) -> None:
    """Write content to file with UTF-8 encoding."""
    file_path.write_text(content, encoding="utf-8")


def init_command(args: argparse.Namespace) -> int:
    """
    Initialize a new SMF project.

    Args:
        args: CLI arguments

    Returns:
        Exit code
    """
    project_path = Path(args.directory)
    if project_path.exists() and not args.force:
        print(f"Error: Directory {project_path} already exists. Use --force to overwrite.")
        return 1

    project_path.mkdir(parents=True, exist_ok=True)

    # Create project structure
    (project_path / "src").mkdir(exist_ok=True)
    tools_dir = project_path / "src" / "tools"
    resources_dir = project_path / "src" / "resources"
    prompts_dir = project_path / "src" / "prompts"
    tests_dir = project_path / "tests"
    
    tools_dir.mkdir(parents=True, exist_ok=True)
    resources_dir.mkdir(parents=True, exist_ok=True)
    prompts_dir.mkdir(parents=True, exist_ok=True)
    tests_dir.mkdir(parents=True, exist_ok=True)
    
    # Create __init__.py files
    write_utf8(tools_dir / "__init__.py", '"""Tools module."""\n')
    write_utf8(resources_dir / "__init__.py", '"""Resources module."""\n')
    write_utf8(prompts_dir / "__init__.py", '"""Prompts module."""\n')
    
    # Create example tool
    example_tool_file = tools_dir / "example_tool.py"
    write_utf8(example_tool_file, '''"""
Example Tools - Demonstrates tool registration.

Tools are functions that perform actions or computations.
They can accept parameters and return results.
"""

from typing import Literal


def greet(name: str) -> str:
    """
    Greet someone by name.
    
    Args:
        name: The name of the person to greet
        
    Returns:
        A greeting message
    """
    return f"Hello, {name}! Welcome to SMF."


def calculate(operation: Literal["add", "subtract", "multiply", "divide"], a: float, b: float) -> float:
    """
    Perform a mathematical calculation.
    
    Args:
        operation: The operation to perform (add, subtract, multiply, divide)
        a: First number
        b: Second number
        
    Returns:
        The result of the calculation
        
    Raises:
        ValueError: If operation is invalid or division by zero
    """
    if operation == "add":
        return a + b
    elif operation == "subtract":
        return a - b
    elif operation == "multiply":
        return a * b
    elif operation == "divide":
        if b == 0:
            raise ValueError("Division by zero is not allowed")
        return a / b
    else:
        raise ValueError(f"Unknown operation: {operation}")
''')
    
    # Create example resource
    example_resource_file = resources_dir / "example_resource.py"
    write_utf8(example_resource_file, '''"""
Example Resources - Demonstrates resource registration.

Resources are data sources that can be read by the LLM.
They're like GET endpoints - they provide information without side effects.
"""

import json
from datetime import datetime


def get_server_info() -> str:
    """
    Get server information as a resource.
    
    Returns:
        JSON string with server information
    """
    info = {
        "server_name": "My SMF Server",
        "version": "1.0.0",
        "status": "running",
        "timestamp": datetime.now().isoformat(),
        "features": [
            "tools",
            "resources",
            "prompts"
        ]
    }
    return json.dumps(info, indent=2)


def get_config() -> str:
    """
    Get server configuration.
    
    Returns:
        Configuration information
    """
    return "Server configuration: Production mode, logging enabled, metrics enabled"
''')
    
    # Create example prompt
    example_prompt_file = prompts_dir / "example_prompt.py"
    write_utf8(example_prompt_file, '''"""
Example Prompts - Demonstrates prompt template registration.

Prompts are reusable templates for LLM interactions.
They define how the assistant should behave and what context to use.
"""


def system_prompt() -> str:
    """
    System prompt template for the assistant.
    
    Returns:
        System prompt text
    """
    return """You are a helpful AI assistant powered by SMF.

You have access to:
- Tools: Functions that can perform actions and calculations
- Resources: Data sources you can read from
- Prompts: Reusable templates for interactions

Use the available tools to help users accomplish their tasks.
Be concise, accurate, and helpful in your responses."""


def code_review_prompt() -> str:
    """
    Prompt template for code review tasks.
    
    Returns:
        Code review prompt
    """
    return """You are an expert code reviewer. Review the provided code and provide:
1. Code quality assessment
2. Potential bugs or issues
3. Performance improvements
4. Best practices recommendations

Be constructive and specific in your feedback."""


def data_analysis_prompt() -> str:
    """
    Prompt template for data analysis tasks.
    
    Returns:
        Data analysis prompt
    """
    return """You are a data analyst. Analyze the provided data and provide:
1. Key insights and patterns
2. Statistical summary
3. Visualizations recommendations
4. Actionable recommendations

Use the available tools to perform calculations and analysis."""
''')
    
    # Create example test
    example_test_file = tests_dir / "test_example.py"
    write_utf8(example_test_file, '''"""
Example tests for SMF server using FastMCP Client.

Based on FastMCP testing patterns:
https://fastmcp.wiki/en/patterns/testing

Run tests with: pytest
"""

import sys
from pathlib import Path

# Add src directory to Python path
src_path = Path(__file__).parent.parent / "src"
if str(src_path) not in sys.path:
    sys.path.insert(0, str(src_path))

import pytest
import pytest_asyncio
from fastmcp.client import Client
from fastmcp.client.transports import FastMCPTransport

from smf import create_server


@pytest.fixture
def mcp():
    """Create test MCP server with example tools."""
    mcp = create_server("Test Server")
    
    # Import and register example tools
    from tools.example_tool import greet as greet_tool, calculate as calculate_tool
    
    @mcp.tool
    def greet(name: str) -> str:
        """Greet someone by name."""
        return greet_tool(name)
    
    @mcp.tool
    def calculate(operation: str, a: float, b: float) -> float:
        """Perform a calculation."""
        return calculate_tool(operation, a, b)
    
    return mcp


@pytest_asyncio.fixture
async def mcp_client(mcp):
    """Create a client connected to the test server."""
    async with Client(transport=mcp) as client:
        yield client


# Unit tests (testing functions directly)
def test_greet_function():
    """Test greet function directly."""
    from tools.example_tool import greet
    result = greet("Alice")
    assert "Alice" in result
    assert "Hello" in result


def test_calculate_add():
    """Test calculate function - addition."""
    from tools.example_tool import calculate
    result = calculate("add", 5, 3)
    assert result == 8


def test_calculate_multiply():
    """Test calculate function - multiplication."""
    from tools.example_tool import calculate
    result = calculate("multiply", 4, 7)
    assert result == 28


def test_calculate_divide():
    """Test calculate function - division."""
    from tools.example_tool import calculate
    result = calculate("divide", 10, 2)
    assert result == 5.0


def test_calculate_divide_by_zero():
    """Test calculate function - division by zero error."""
    from tools.example_tool import calculate
    with pytest.raises(ValueError, match="Division by zero"):
        calculate("divide", 10, 0)


# Integration tests (testing via MCP Client)
@pytest.mark.asyncio
async def test_list_tools(mcp_client: Client[FastMCPTransport]):
    """Test listing tools via MCP client."""
    tools = await mcp_client.list_tools()
    assert len(tools) >= 2
    tool_names = [tool.name for tool in tools]
    assert "greet" in tool_names
    assert "calculate" in tool_names


@pytest.mark.parametrize(
    "name, expected_contains",
    [
        ("Alice", "Alice"),
        ("Bob", "Bob"),
        ("World", "World"),
    ],
)
@pytest.mark.asyncio
async def test_greet_tool(
    name: str,
    expected_contains: str,
    mcp_client: Client[FastMCPTransport],
):
    """Test greet tool via MCP client with parametrize."""
    result = await mcp_client.call_tool(name="greet", arguments={"name": name})
    assert result.data is not None
    assert isinstance(result.data, str)
    assert expected_contains in result.data


@pytest.mark.parametrize(
    "operation, a, b, expected",
    [
        ("add", 1, 2, 3),
        ("add", 5, 3, 8),
        ("multiply", 4, 7, 28),
        ("multiply", 2, 3, 6),
        ("divide", 10, 2, 5.0),
        ("divide", 15, 3, 5.0),
        ("subtract", 10, 3, 7),
    ],
)
@pytest.mark.asyncio
async def test_calculate_tool(
    operation: str,
    a: float,
    b: float,
    expected: float,
    mcp_client: Client[FastMCPTransport],
):
    """Test calculate tool via MCP client with parametrize."""
    result = await mcp_client.call_tool(
        name="calculate",
        arguments={"operation": operation, "a": a, "b": b}
    )
    assert result.data is not None
    assert isinstance(result.data, (int, float))
    assert result.data == expected
''')

    # Create main server file
    server_file = project_path / "server.py"
    write_utf8(server_file,
        '''"""
SMF Server - Main entry point.

This server demonstrates:
- Tools: Functions that perform actions
- Resources: Data sources that can be read
- Prompts: Reusable prompt templates
"""

import sys
from pathlib import Path

# Add src directory to Python path
src_path = Path(__file__).parent / "src"
if str(src_path) not in sys.path:
    sys.path.insert(0, str(src_path))

from smf import create_server

# Create server
mcp = create_server()

# Import example components
from tools.example_tool import greet as greet_tool, calculate as calculate_tool
from resources.example_resource import get_server_info
from prompts.example_prompt import system_prompt

# Register tools
@mcp.tool
def greet(name: str) -> str:
    """Greet someone by name."""
    return greet_tool(name)

@mcp.tool
def calculate(operation: str, a: float, b: float) -> float:
    """Perform a calculation."""
    return calculate_tool(operation, a, b)

# Register resources
@mcp.resource("server://info")
def server_info() -> str:
    """Get server information."""
    return get_server_info()

# Register prompts
@mcp.prompt
def system() -> str:
    """System prompt template."""
    return system_prompt()

if __name__ == "__main__":
    mcp.run()
''')

    # Create settings file
    settings_file = project_path / "smf.yaml"
    default_settings = Settings().model_dump(exclude_none=True, mode="json")
    try:
        import yaml
        with open(settings_file, "w") as f:
            yaml.dump(default_settings, f, default_flow_style=False, sort_keys=False)
    except ImportError:
        # Fallback to JSON if PyYAML not available
        import json
        settings_file = project_path / "smf.json"
        with open(settings_file, "w") as f:
            json.dump(default_settings, f, indent=2)

    # Create requirements.txt
    requirements_file = project_path / "requirements.txt"
    write_utf8(requirements_file,
        '''smf
fastmcp
pytest
pytest-asyncio
''')

    # Create README
    readme_file = project_path / "README.md"
    project_name = args.name or 'SMF Server'
    readme_content = f"""# {project_name}

Serveur MCP créé avec SMF (Enterprise MCP Framework).

## 🚀 Démarrage rapide

### Installation

```bash
# Installer les dépendances
uv add smf fastmcp pytest pytest-asyncio

# Ou avec pip
pip install -r requirements.txt
```

### Lancer le serveur

```bash
# Mode stdio (développement local)
python server.py

# Mode HTTP (accès distant)
python server.py --transport http --port 8000
```

## 📁 Structure du projet

```
{project_name}/
├── server.py              # Point d'entrée principal du serveur
├── smf.yaml              # Configuration SMF
├── src/
│   ├── tools/             # Définitions d'outils (tools)
│   │   └── example_tool.py
│   ├── resources/         # Définitions de ressources
│   │   └── example_resource.py
│   └── prompts/           # Templates de prompts
│       └── example_prompt.py
└── tests/                 # Tests unitaires
    └── test_example.py
```

## 🛠️ Composants inclus

### Tools (Outils)

Le projet inclut des exemples d'outils dans `src/tools/example_tool.py`:
- `greet(name)`: Salue quelqu'un par son nom
- `calculate(operation, a, b)`: Effectue des calculs mathématiques

### Resources (Ressources)

Exemples dans `src/resources/example_resource.py`:
- `get_server_info()`: Obtient des informations sur le serveur
- `get_config()`: Obtient la configuration

### Prompts

Exemples dans `src/prompts/example_prompt.py`:
- `system_prompt()`: Prompt système pour l'assistant
- `code_review_prompt()`: Template pour révision de code
- `data_analysis_prompt()`: Template pour analyse de données

## ➕ Ajouter un nouvel outil

```bash
smf add-tool mon-outil --description "Description de mon outil"
```

Cela crée `src/tools/mon-outil.py`. Ensuite, importez et enregistrez-le dans `server.py`:

```python
from src.tools.mon_outil import mon_outil

@mcp.tool
def mon_outil(...):
    return mon_outil(...)
```

## ⚙️ Configuration

Modifiez `smf.yaml` pour personnaliser:
- Nom et version du serveur
- Transport (stdio/http/sse)
- Logging et métriques
- Rate limiting
- Authentification

## 🧪 Tests

```bash
# Lancer les tests
pytest

# Avec couverture
pytest --cov=src
```

## 📚 Documentation

- [Guide SMF](https://github.com/your-repo/smf)
- [Documentation FastMCP](https://fastmcp.wiki/)
- [Architecture SMF](./src/docs/architecture.md)

## 🔧 Commandes CLI

```bash
# Initialiser un projet
smf init mon-projet

# Ajouter un outil
smf add-tool nom-outil --description "Description"

# Valider la configuration
smf validate --config smf.yaml

# Lancer le serveur
smf run server.py --transport http --port 8000
```

## 📝 Exemples

Voir les exemples dans:
- `src/examples/simple_server/` - Serveur simple
- `src/examples/advanced_server/` - Serveur avancé avec configuration

## 🤝 Contribution

Ce projet utilise SMF, un framework enterprise pour créer des serveurs MCP.

Pour plus d'informations, consultez la documentation SMF.
"""
    # Write with UTF-8 encoding to support emojis
    write_utf8(readme_file, readme_content)

    print(f"✓ Created SMF project in {project_path}")
    return 0


def add_tool_command(args: argparse.Namespace) -> int:
    """
    Add a new tool template.

    Args:
        args: CLI arguments

    Returns:
        Exit code
    """
    tool_name = args.name
    
    # Detect project directory (look for smf.yaml or smf.json)
    project_dir = Path(args.directory).resolve()
    if not (project_dir / "smf.yaml").exists() and not (project_dir / "smf.json").exists():
        # Try parent directory
        if (project_dir.parent / "smf.yaml").exists() or (project_dir.parent / "smf.json").exists():
            project_dir = project_dir.parent
        else:
            # Use current directory
            project_dir = Path(".").resolve()
    
    tool_file = project_dir / "src" / "tools" / f"{tool_name}.py"

    if tool_file.exists() and not args.force:
        print(f"Error: Tool {tool_name} already exists. Use --force to overwrite.")
        return 1

    tool_file.parent.mkdir(parents=True, exist_ok=True)

    # Create __init__.py if it doesn't exist
    init_file = tool_file.parent / "__init__.py"
    if not init_file.exists():
        write_utf8(init_file, '"""Tools module."""\n')

    template = f'''"""
Tool: {tool_name}
{args.description or 'Tool description'}
"""

from typing import Any


def {tool_name}(*args: Any, **kwargs: Any) -> Any:
    """
    {args.description or 'Tool description'}
    
    Args:
        *args: Tool arguments
        **kwargs: Tool keyword arguments
        
    Returns:
        Tool result
    """
    # TODO: Implement tool logic
    return {{"result": "not implemented"}}
'''
    write_utf8(tool_file, template)

    print(f"✓ Created tool template: {tool_file}")
    print(f"  To use it, import and register in server.py:")
    print(f"    from src.tools.{tool_name} import {tool_name}")
    print(f"    @mcp.tool")
    print(f"    {tool_name}")
    return 0


def validate_command(args: argparse.Namespace) -> int:
    """
    Validate SMF configuration.

    Args:
        args: CLI arguments

    Returns:
        Exit code
    """
    config_file = Path(args.config)
    if not config_file.exists():
        print(f"Error: Config file not found: {config_file}")
        return 1

    try:
        settings = Settings.from_file(config_file)
        print("✓ Configuration is valid")
        print(f"  Server name: {settings.server_name}")
        print(f"  Transport: {settings.transport}")
        print(f"  Auth provider: {settings.auth_provider}")
        return 0
    except Exception as e:
        print(f"✗ Configuration error: {e}")
        return 1


def run_command(args: argparse.Namespace) -> int:
    """
    Run SMF server.

    Args:
        args: CLI arguments

    Returns:
        Exit code
    """
    server_file = Path(args.server)
    if not server_file.exists():
        print(f"Error: Server file not found: {server_file}")
        return 1

    # Import and run server
    import importlib.util

    spec = importlib.util.spec_from_file_location("server", server_file)
    if spec is None or spec.loader is None:
        print(f"Error: Cannot import server from {server_file}")
        return 1

    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)

    # Find mcp instance
    if not hasattr(module, "mcp"):
        print("Error: Server module must define 'mcp' variable")
        return 1

    mcp = module.mcp

    # Run server
    from smf.transport import run_server

    try:
        run_server(mcp, transport=args.transport, host=args.host, port=args.port)
    except KeyboardInterrupt:
        try:
            print("\nServer stopped", file=sys.stderr)
        except ValueError:
            pass
        return 0
    except Exception as e:
        print(f"Error running server: {e}")
        return 1


def init_elasticsearch_command(args: argparse.Namespace) -> int:
    """
    Initialize a new SMF project with Elasticsearch plugin.

    Args:
        args: CLI arguments

    Returns:
        Exit code
    """
    project_path = Path(args.directory)
    if project_path.exists() and not args.force:
        print(f"Error: Directory {project_path} already exists. Use --force to overwrite.")
        return 1

    project_path.mkdir(parents=True, exist_ok=True)

    # Create project structure
    (project_path / "src").mkdir(exist_ok=True)
    tools_dir = project_path / "src" / "tools"
    tests_dir = project_path / "tests"
    
    tools_dir.mkdir(parents=True, exist_ok=True)
    tests_dir.mkdir(parents=True, exist_ok=True)
    
    # Create __init__.py files
    write_utf8(tools_dir / "__init__.py", '"""Tools module."""\n')

    # Get configuration
    es_hosts = args.hosts or "http://localhost:9200"
    default_index = args.index or "my_index"
    server_name = args.name or f"Elasticsearch SMF Server ({default_index})"

    # Create server.py with Elasticsearch setup
    server_file = project_path / "server.py"
    write_utf8(server_file, f'''"""
SMF Elasticsearch Server - Main entry point.

This server provides Elasticsearch tools for the "{default_index}" index.
"""

import sys
import os
from pathlib import Path

# Add src directory to Python path
sys.path.insert(0, str(Path(__file__).parent / "src"))

from smf import create_server

# Try to import Elasticsearch plugin
try:
    from smf.plugins.elasticsearch import (
        ElasticsearchClient,
        create_elasticsearch_tools,
    )
except ImportError:
    print("Error: elasticsearch plugin not installed.")
    print("Install with: pip install smf[elasticsearch] or uv add smf[elasticsearch]")
    sys.exit(1)

# Create Elasticsearch client
# Configuration via environment variables:
# - ELASTICSEARCH_HOSTS: Elasticsearch host(s) (default: {es_hosts})
# - ELASTICSEARCH_API_KEY: Optional API key
# - ELASTICSEARCH_USERNAME: Optional username for basic auth
# - ELASTICSEARCH_PASSWORD: Optional password for basic auth

es_hosts = os.getenv("ELASTICSEARCH_HOSTS", "{es_hosts}")
es_config = {{"hosts": es_hosts}}

# Add authentication if provided
if os.getenv("ELASTICSEARCH_API_KEY"):
    es_config["api_key"] = os.getenv("ELASTICSEARCH_API_KEY")
elif os.getenv("ELASTICSEARCH_USERNAME") and os.getenv("ELASTICSEARCH_PASSWORD"):
    es_config["basic_auth"] = (
        os.getenv("ELASTICSEARCH_USERNAME"),
        os.getenv("ELASTICSEARCH_PASSWORD"),
    )

try:
    es_client = ElasticsearchClient(**es_config)
    print(f"✓ Connected to Elasticsearch at {{es_hosts}}")
except Exception as e:
    print(f"Error connecting to Elasticsearch: {{e}}")
    print("Make sure Elasticsearch is running and accessible.")
    sys.exit(1)

# Create SMF server
mcp = create_server("{server_name}")

# Create and register Elasticsearch tools
print(f"✓ Registering Elasticsearch tools for index: {default_index}")
es_tools = create_elasticsearch_tools(
    es_client=es_client,
    index="{default_index}",
    tags=["elasticsearch", "search"],
)

for tool in es_tools:
    mcp.tool(tool)

# You can add custom Elasticsearch tools here
# Example:
# @mcp.tool(tags=["elasticsearch", "custom"])
# def custom_search(query: str, filters: dict = None) -> dict:
#     \"\"\"Custom search with filters.\"\"\"
#     es_query = {{"query": {{"match": {{"_all": query}}}}}}
#     if filters:
#         es_query["query"]["bool"] = {{"filter": filters}}
#     return es_client.search(index="{default_index}", query=es_query)

print(f"✓ Server '{server_name}' ready with {{len(es_tools)}} Elasticsearch tools")
print(f"✓ Default index: {default_index}")

if __name__ == "__main__":
    mcp.run()
''')

    # Create .env.example
    env_example_file = project_path / ".env.example"
    write_utf8(env_example_file, f'''# Elasticsearch Configuration
ELASTICSEARCH_HOSTS={es_hosts}
# ELASTICSEARCH_API_KEY=your-api-key-here
# ELASTICSEARCH_USERNAME=your-username
# ELASTICSEARCH_PASSWORD=your-password

# SMF Configuration
SMF_SERVER_NAME={server_name}
SMF_STRUCTURED_LOGGING=true
SMF_METRICS_ENABLED=true
''')

    # Create smf.yaml
    settings_file = project_path / "smf.yaml"
    default_settings = Settings(
        server_name=server_name,
        structured_logging=True,
        metrics_enabled=True,
    ).model_dump(exclude_none=True, mode="json")
    
    try:
        import yaml
        with open(settings_file, "w", encoding="utf-8") as f:
            yaml.dump(default_settings, f, default_flow_style=False, sort_keys=False)
    except ImportError:
        import json
        settings_file = project_path / "smf.json"
        with open(settings_file, "w", encoding="utf-8") as f:
            json.dump(default_settings, f, indent=2)

    # Create README
    readme_file = project_path / "README.md"
    write_utf8(readme_file, f'''# {server_name}

SMF server with Elasticsearch integration for the `{default_index}` index.

## Setup

1. **Install dependencies:**
   ```bash
   uv add smf[elasticsearch]
   # or
   pip install smf[elasticsearch]
   ```

2. **Configure Elasticsearch connection:**
   
   Copy `.env.example` to `.env` and configure:
   ```bash
   cp .env.example .env
   ```
   
   Edit `.env` with your Elasticsearch settings:
   ```bash
   ELASTICSEARCH_HOSTS=http://localhost:9200
   ELASTICSEARCH_API_KEY=your-api-key  # Optional
   ```

3. **Start Elasticsearch** (if running locally):
   ```bash
   docker run -d -p 9200:9200 -e "discovery.type=single-node" elasticsearch:8.0.0
   ```

## Usage

### Run the server:
```bash
smf run server.py
```

### Test with inspector:
```bash
smf-inspector server.py:mcp
```

### Available Tools

The server provides these Elasticsearch tools:

- **search_tool** - Search documents in the `{default_index}` index
- **get_document_tool** - Get a document by ID
- **index_document_tool** - Index a new document
- **list_indices_tool** - List all Elasticsearch indices
- **cluster_health_tool** - Get cluster health information

## Customization

Edit `server.py` to add custom Elasticsearch tools or modify existing ones.

## Environment Variables

- `ELASTICSEARCH_HOSTS` - Elasticsearch host(s) (default: {es_hosts})
- `ELASTICSEARCH_API_KEY` - API key for authentication (optional)
- `ELASTICSEARCH_USERNAME` - Username for basic auth (optional)
- `ELASTICSEARCH_PASSWORD` - Password for basic auth (optional)
''')

    # Create requirements.txt
    requirements_file = project_path / "requirements.txt"
    write_utf8(requirements_file, '''smf[elasticsearch]>=0.1.0
''')

    print(f"\n✓ Elasticsearch SMF server created in '{project_path}'")
    print(f"\nNext steps:")
    print(f"  1. cd {project_path}")
    print(f"  2. Configure .env file with your Elasticsearch settings")
    print(f"  3. Run: smf run server.py")
    print(f"  4. Test: smf-inspector server.py:mcp")
    
    return 0


def activate_plugin_command(args: argparse.Namespace) -> int:
    """
    Activate a plugin in an existing SMF project.
    
    Args:
        args: CLI arguments
        
    Returns:
        Exit code
    """
    plugin_name = args.plugin
    target_dir = Path(args.directory).resolve()
    
    if not target_dir.exists():
        print(f"Error: Directory {target_dir} does not exist.")
        return 1
        
    # Check if it's a valid SMF project (has server.py or smf.yaml/json)
    if not (target_dir / "server.py").exists():
        print(f"Warning: {target_dir} does not appear to be a standard SMF project (missing server.py).")
        if not args.force:
            print("Use --force to proceed anyway.")
            return 1
            
    if plugin_name == "elasticsearch":
        return _activate_elasticsearch(target_dir, args)
    else:
        print(f"Error: Unknown plugin '{plugin_name}'. Available plugins: elasticsearch")
        return 1


def _activate_elasticsearch(project_path: Path, args: argparse.Namespace) -> int:
    """Activate Elasticsearch plugin."""
    print(f"Activating Elasticsearch plugin in {project_path}...")
    
    # 1. Create custom tools file
    tools_dir = project_path / "src" / "tools"
    tools_dir.mkdir(parents=True, exist_ok=True)
    
    custom_tool_file = tools_dir / "elasticsearch_custom.py"
    
    if custom_tool_file.exists() and not args.force:
        print(f"Warning: {custom_tool_file} already exists. Skipping creation.")
    else:
        # Read template content
        try:
            from smf.templates.elasticsearch_custom import create_custom_tools
            # We need the source code of the module, not the function
            import inspect
            import smf.templates.elasticsearch_custom as template_module
            content = inspect.getsource(template_module)
        except ImportError:
             # Fallback if template module not found in path yet (dev mode)
             content = '''"""
Custom Elasticsearch Tools Template.

This module provides a starting point for creating custom Elasticsearch tools.
"""

from typing import Any, Dict, List, Optional

from smf.plugins.elasticsearch import ElasticsearchClient


def create_custom_tools(es_client: ElasticsearchClient, index: str) -> List[Any]:
    """
    Create custom Elasticsearch tools.
    
    Args:
        es_client: The Elasticsearch client instance
        index: The default index to operate on
        
    Returns:
        List of tool functions
    """
    
    def advanced_search(
        query: str,
        filters: Optional[Dict[str, Any]] = None,
        size: int = 10
    ) -> Dict[str, Any]:
        """
        Perform an advanced search with optional filters.
        
        Args:
            query: The search query string
            filters: Optional dictionary of filters (term, range, etc.)
            size: Number of results to return (default: 10)
            
        Returns:
            Search results
        """
        # Build the Elasticsearch query
        es_query = {
            "query": {
                "bool": {
                    "must": [
                        {"query_string": {"query": query}}
                    ]
                }
            }
        }
        
        # Add filters if provided
        if filters:
            filter_clauses = []
            for field, value in filters.items():
                if isinstance(value, list):
                    filter_clauses.append({"terms": {field: value}})
                else:
                    filter_clauses.append({"term": {field: value}})
            
            es_query["query"]["bool"]["filter"] = filter_clauses
            
        return es_client.search(
            index=index,
            query=es_query,
            size=size
        )
        
    # Return the tool functions
    return [advanced_search]
'''
        write_utf8(custom_tool_file, content)
        print(f"✓ Created {custom_tool_file}")

    # 2. Update .env file
    env_file = project_path / ".env"
    es_hosts = args.hosts or "http://localhost:9200"
    
    env_content = ""
    if env_file.exists():
        env_content = env_file.read_text(encoding="utf-8")
    
    if "ELASTICSEARCH_HOSTS" not in env_content:
        new_env_config = f'''
# Elasticsearch Configuration
ELASTICSEARCH_HOSTS={es_hosts}
# ELASTICSEARCH_API_KEY=your-api-key-here
# ELASTICSEARCH_USERNAME=your-username
# ELASTICSEARCH_PASSWORD=your-password
'''
        with open(env_file, "a", encoding="utf-8") as f:
            f.write(new_env_config)
        print(f"✓ Updated {env_file} with Elasticsearch configuration")
    else:
        print(f"ℹ .env already contains Elasticsearch configuration")

    # 3. Update requirements.txt
    req_file = project_path / "requirements.txt"
    if req_file.exists():
        req_content = req_file.read_text(encoding="utf-8")
        if "smf[elasticsearch]" not in req_content:
            with open(req_file, "a", encoding="utf-8") as f:
                f.write("\nsmf[elasticsearch]\n")
            print(f"✓ Added smf[elasticsearch] to requirements.txt")
    else:
        write_utf8(req_file, "smf[elasticsearch]\n")
        print(f"✓ Created requirements.txt")

    # 4. Instructions
    print("\n✓ Elasticsearch plugin activated!")
    print("\nNext steps:")
    print("1. Install dependencies:")
    print("   uv add smf[elasticsearch]")
    print("\n2. Update your server.py to register the plugin:")
    print("""
    from smf.plugins.elasticsearch import ElasticsearchClient, create_elasticsearch_tools
    from src.tools.elasticsearch_custom import create_custom_tools
    import os

    # Setup Elasticsearch
    es_client = ElasticsearchClient(hosts=os.getenv("ELASTICSEARCH_HOSTS", "http://localhost:9200"))
    
    # Register standard tools
    es_tools = create_elasticsearch_tools(es_client, index="my_index")
    for tool in es_tools:
        mcp.tool(tool)
        
    # Register custom tools
    custom_tools = create_custom_tools(es_client, index="my_index")
    for tool in custom_tools:
        mcp.tool(tool)
    """)
    
    return 0


def main() -> int:
    """Main CLI entry point."""
    import importlib.metadata
    
    try:
        version = importlib.metadata.version("smf-mcp")
    except importlib.metadata.PackageNotFoundError:
        version = "unknown"

    parser = argparse.ArgumentParser(description="SMF - Enterprise MCP Framework")
    parser.add_argument(
        "--version", 
        action="version", 
        version=f"%(prog)s {version}",
        help="Show the version and exit"
    )
    subparsers = parser.add_subparsers(dest="command", help="Command to run")

    # Init command
    init_parser = subparsers.add_parser("init", help="Initialize new project")
    init_parser.add_argument("directory", help="Project directory")
    init_parser.add_argument("--name", help="Project name")
    init_parser.add_argument("--force", action="store_true", help="Overwrite existing")

    # Init Elasticsearch command
    init_es_parser = subparsers.add_parser(
        "init-elasticsearch",
        help="Initialize new Elasticsearch SMF server"
    )
    init_es_parser.add_argument("directory", help="Project directory")
    init_es_parser.add_argument("--name", help="Server name")
    init_es_parser.add_argument(
        "--hosts",
        default="http://localhost:9200",
        help="Elasticsearch hosts (default: http://localhost:9200)"
    )
    init_es_parser.add_argument(
        "--index",
        help="Default Elasticsearch index name (default: my_index)"
    )
    init_es_parser.add_argument("--force", action="store_true", help="Overwrite existing")

    # Add tool command
    add_tool_parser = subparsers.add_parser("add-tool", help="Add new tool")
    add_tool_parser.add_argument("name", help="Tool name")
    add_tool_parser.add_argument("--directory", default=".", help="Project directory")
    add_tool_parser.add_argument("--description", help="Tool description")
    add_tool_parser.add_argument("--force", action="store_true", help="Overwrite existing")

    # Validate command
    validate_parser = subparsers.add_parser("validate", help="Validate configuration")
    validate_parser.add_argument("--config", default="smf.yaml", help="Config file path")

    # Run command
    run_parser = subparsers.add_parser("run", help="Run server")
    run_parser.add_argument("server", help="Server file path")
    run_parser.add_argument("--transport", default="stdio", help="Transport type")
    run_parser.add_argument("--host", help="HTTP host")
    run_parser.add_argument("--port", type=int, help="HTTP port")

    # Activate plugin command
    activate_parser = subparsers.add_parser("activate-plugin", help="Activate a plugin in existing project")
    activate_parser.add_argument("plugin", choices=["elasticsearch"], help="Plugin to activate")
    activate_parser.add_argument("--directory", default=".", help="Target directory (default: current)")
    activate_parser.add_argument("--hosts", help="Elasticsearch hosts (for elasticsearch plugin)")
    activate_parser.add_argument("--force", action="store_true", help="Force activation even if validation fails")

    args = parser.parse_args()

    if not args.command:
        parser.print_help()
        return 1

    if args.command == "init":
        return init_command(args)
    elif args.command == "init-elasticsearch":
        return init_elasticsearch_command(args)
    elif args.command == "add-tool":
        return add_tool_command(args)
    elif args.command == "validate":
        return validate_command(args)
    elif args.command == "run":
        return run_command(args)
    elif args.command == "activate-plugin":
        return activate_plugin_command(args)
    else:
        parser.print_help()
        return 1


if __name__ == "__main__":
    sys.exit(main())

