#!/usr/bin/env python3
"""
Main CLI entry point for n8n-deploy

Handles CLI initialization, version/help commands, and basic CLI infrastructure.
"""

from typing import Any, List, Optional

import click
from rich.console import Console

console = Console()

# Program name constant for consistent CLI help messages
PROG_NAME = "n8n-deploy|./n8n-deploy"

# Common CLI option help texts
cli_data_dir_help = "Data directory for database and backups"
HELP_FLOW_DIR = "Plain directory where wf JSON files are located"
HELP_DB_FILENAME = "Database filename (default: n8n-deploy.db)"
HELP_SERVER_URL = "n8n server URL (overrides N8N_SERVER_URL)"
HELP_NO_EMOJI = "Disable emoji output for automation/scripting"
HELP_JSON = "Output in JSON format for scripting/automation"
HELP_FORMAT = "Output format"  # Deprecated - use HELP_JSON/HELP_TABLE
HELP_TABLE = "Output in table format (default for interactive use)"


class CustomCommand(click.Command):
    """Custom Click Command that shows consistent usage format"""

    def format_usage(self, ctx: click.Context, formatter: click.HelpFormatter) -> None:
        """Override format_usage to show consistent usage across all commands"""
        # Build the command path
        pieces: List[str] = []
        current_ctx: Optional[click.Context] = ctx
        while current_ctx is not None:
            if current_ctx.info_name:
                pieces.insert(0, current_ctx.info_name)
            current_ctx = current_ctx.parent

        # Build usage line showing the full command path
        command_path = " ".join(pieces[1:]) if len(pieces) > 1 else ""

        # Collect arguments for this command, preferring metavar over name
        args_str = ""
        if hasattr(self, "params"):
            args = []
            for p in self.params:
                if isinstance(p, click.Argument) and p.name:
                    # Use metavar if available, otherwise uppercase name
                    arg_display = p.metavar if hasattr(p, "metavar") and p.metavar else p.name.upper()
                    args.append(arg_display)
            if args:
                args_str = " " + " ".join(args)

        if command_path:
            usage_line = f"n8n-deploy|./n8n-deploy {command_path}{args_str} [OPTIONS]..."
        else:
            usage_line = "n8n-deploy|./n8n-deploy COMMAND [OPTIONS]..."

        formatter.write(f"Usage: {usage_line}\n\n")


class CustomGroup(click.Group):
    """Custom Click Group that formats usage as 'COMMAND [OPTIONS]...' instead of '[OPTIONS] COMMAND [ARGS]...'"""

    def get_command(self, ctx: click.Context, cmd_name: str) -> Optional[click.Command]:
        """Override to disable prefix matching - require exact command names"""
        return self.commands.get(cmd_name)

    def collect_usage_pieces(self, ctx: click.Context) -> List[str]:
        """Override to collect custom usage pieces"""
        # Get the original pieces first for the program name
        original_pieces = super().collect_usage_pieces(ctx)
        rv = []
        # Keep the program name from the original
        if original_pieces:
            rv.append(original_pieces[0])
        # Add just the command part - we'll handle OPTIONS separately
        rv.append("COMMAND")
        return rv

    def format_usage(self, ctx: click.Context, formatter: click.HelpFormatter) -> None:
        """Override format_usage to completely control the output"""
        # Build the complete usage string we want
        usage_line = "n8n-deploy|./n8n-deploy COMMAND [OPTIONS]..."

        # Write it directly
        formatter.write(f"Usage: {usage_line}\n\n")

    def parse_args(self, ctx: click.Context, args: List[str]) -> List[str]:
        """Override to handle version/help mutual exclusion and no-args behavior"""
        # Check for both --help and --version
        has_help = any(arg in ["--help", "-h"] for arg in args)
        has_version = "--version" in args

        if has_help and has_version:
            # Silently exit when both are used
            ctx.exit(0)

        return super().parse_args(ctx, args)

    def __call__(self, *args: Any, **kwargs: Any) -> Any:
        """Override __call__ to handle no-args case with exit code 0"""
        import sys

        try:
            return super().__call__(*args, **kwargs)
        except Exception as e:
            # Handle NoArgsIsHelpError at runtime (not in type stubs)
            if e.__class__.__name__ == "NoArgsIsHelpError":
                print(str(e))
                sys.exit(0)
            raise


def handle_version_help(ctx: click.Context, _param: click.Parameter, value: Any) -> None:
    """Handle version/help mutual exclusion - silently ignore when both used"""
    if not value or ctx.resilient_parsing:
        return

    # Check if both version and help are requested
    import sys

    args = sys.argv[1:]
    has_help = any(arg in ["--help", "-h"] for arg in args)
    has_version = "--version" in args

    if has_help and has_version:
        # Silently ignore when both are used - exit with no output
        ctx.exit(0)

    # Show version from package metadata
    try:
        from importlib.metadata import version

        pkg_version = version("n8n-deploy")
    except Exception:
        from api import __version__

        pkg_version = __version__
    click.echo(f"n8n-deploy, version {pkg_version}")
    ctx.exit()


@click.group(cls=CustomGroup, context_settings={"help_option_names": ["-h", "--help"]}, no_args_is_help=True)
@click.option(
    "--version", is_flag=True, expose_value=False, is_eager=True, callback=handle_version_help, help="Show version and exit"
)
def cli() -> None:
    """🎭 n8n-deploy - a simple N8N Workflow Manager

    Use 'n8n-deploy COMMAND --help' for detailed command options.

    ⚠️  NOTE: Run 'n8n-deploy db init' before using other commands.

    \b
    📂 Core Directories:

    \b
    App Directory ('--data-dir'):
      Stores application data (database, backups)
      Priority: '--data-dir' CLI option > N8N_DEPLOY_DATA_DIR env var > current directory
      Default file: n8n-deploy.db

    \b
    Flow Directory ('--flow-dir'):
      Contains wf JSON files
      Priority: '--flow-dir' CLI option > N8N_DEPLOY_FLOWS_DIR env var > current directory
      Default: current directory

    \b
    🌐 Server Configuration:
      n8n Server URL: '--remote' CLI option > N8N_SERVER_URL env var
      API Keys: Stored in database, managed via 'apikey' commands
    """
    pass


# Register command groups
def register_commands() -> None:
    """Register all command groups with the main CLI"""
    from .apikey import apikey
    from .db import db
    from .env import env
    from .server import server
    from .wf import wf

    # Register command groups
    cli.add_command(wf)
    cli.add_command(db)
    cli.add_command(apikey)
    cli.add_command(server)
    cli.add_command(env)


# Auto-register commands when module is imported
register_commands()


# This will be the main CLI app that other modules will extend
def get_cli_app() -> click.Group:
    """Get the main CLI application with all commands registered"""
    register_commands()
    return cli


if __name__ == "__main__":
    register_commands()
    cli()
