import json
from pathlib import Path
from typing import List, Optional
from typing_extensions import Annotated
import typer
from rich.console import Console
from typing_extensions import Annotated

from project_generator.infrastructure.entry_points.cli.parsers import (
    ToolDefinitionParser,
    PromptDefinitionParser,
    ResourceDefinitionParser
)

from project_generator.applications.settings.container import container
from project_generator.infrastructure.entry_points.cli.handlers import CLIHandlers

console = Console()
app = typer.Typer(help="Generate and manage MCP projects from scaffolds")


@app.command("from-file")
def generate_from_file(
    config_file: Annotated[Path, typer.Option("--config", "-c", help="Path to JSON config file.", exists=True, resolve_path=True)],
    output_dir: Annotated[Path, typer.Option("--output-dir", "-o", help="Output directory.")] = Path.cwd()
):
    """Creates a new MCP project from a JSON config file."""
    from project_generator.applications.settings.container import container
    from project_generator.infrastructure.entry_points.cli.handlers import CLIHandlers
    
    cli_handlers = CLIHandlers(
        generation_use_case=container.generation_use_case(), 
        console=console
    )
    cli_handlers.handle_from_file(config_file, output_dir)

@app.command("restore-backup")
def restore_backup(
    backup_name: Annotated[Optional[str], typer.Argument(help="Nombre del backup a restaurar (ej: backup_YYYYMMDD_HHMMSS). Si se omite, se listarán los disponibles.")] = None,
    force: Annotated[bool, typer.Option("--force", "-f", help="Forzar restauración sin confirmación.")] = False
):
    """Lista backups disponibles o restaura un proyecto desde un backup específico."""
    cli_handlers = CLIHandlers(
        restore_use_case=container.restore_backup_use_case(),
        analyzer=container.project_analyzer_adapter(),
        console=console
    )
    cli_handlers.handle_restore_backup(backup_name, force)

@app.command("create")
def generate_direct(
    project_name: Annotated[str, typer.Argument(help="Name of the MCP project")],
    tools: Annotated[List[str], typer.Option("--tool", "-t", help="Tool: 'name|desc|params|return'")] = [],
    prompts: Annotated[List[str], typer.Option("--prompt", "-p", help="Prompt: 'name|desc'")] = [],
    resources: Annotated[List[str], typer.Option("--resource", "-r", help="Resource: 'name|uri|desc|params|return'")] = [],
    output_dir: Annotated[Path, typer.Option("--output-dir", "-o", help="Output directory.")] = Path.cwd(),
    no_zip: Annotated[bool, typer.Option("--no-zip", help="Generate project files directly without creating a zip archive.")] = False
):
    """Creates a new MCP project via command line arguments."""
    from project_generator.applications.settings.container import container
    from project_generator.infrastructure.entry_points.cli.handlers import CLIHandlers
    
    cli_handlers = CLIHandlers(
        generation_use_case=container.generation_use_case(),
        tool_parser=ToolDefinitionParser(),
        prompt_parser=PromptDefinitionParser(),
        resource_parser=ResourceDefinitionParser(),
        console=console
    )
    cli_handlers.handle_create(project_name, tools, prompts, resources, output_dir, no_zip)


@app.command("interactive")
def generate_interactive(
    output_dir: Annotated[Path, typer.Option("--output-dir", "-o", help="Output directory.")] = Path.cwd()
):
    """Creates a new MCP project interactively."""
    from project_generator.applications.settings.container import container
    from project_generator.infrastructure.entry_points.cli.handlers import CLIHandlers
    
    cli_handlers = CLIHandlers(
        generation_use_case=container.generation_use_case(),
        tool_parser=ToolDefinitionParser(),
        prompt_parser=PromptDefinitionParser(),
        resource_parser=ResourceDefinitionParser(),
        console=console
    )
    cli_handlers.handle_interactive(output_dir)


@app.command("add")
def add_to_project(
    tools: Annotated[List[str], typer.Option("--tool", "-t", help="Tool to add: 'name|desc|params|return'")] = [],
    prompts: Annotated[List[str], typer.Option("--prompt", "-p", help="Prompt to add: 'name|desc'")] = [],
    resources: Annotated[List[str], typer.Option("--resource", "-r", help="Resource to add: 'name|uri|desc|params|return'")] = [],
):
    """Adds new components to an existing MCP project."""
    from project_generator.applications.settings.container import container
    from project_generator.infrastructure.entry_points.cli.handlers import CLIHandlers
    
    cli_handlers = CLIHandlers(
        update_use_case=container.update_project_use_case(),
        tool_parser=ToolDefinitionParser(),
        prompt_parser=PromptDefinitionParser(),
        resource_parser=ResourceDefinitionParser(),
        console=console,
        analyzer=container.project_analyzer_adapter()
    )
    cli_handlers.handle_add(tools, prompts, resources)


@app.callback(invoke_without_command=True)
def default_command(ctx: typer.Context):
    if ctx.invoked_subcommand is None:
        console.print(ctx.get_help())


def main():
    app()


if __name__ == "__main__":
    main()