# ABOUTME: Core CLI setup with AsyncTyper wrapper and base configuration
# ABOUTME: Provides main CLI entry point and logging configuration
import importlib.metadata
import inspect
from functools import partial, wraps

import asyncer
import typer
from rich.console import Console
from rich.table import Table

from vibetuner.cli.db import db_app
from vibetuner.cli.notify import notify_app
from vibetuner.cli.run import run_app
from vibetuner.cli.scaffold import scaffold_app
from vibetuner.importer import import_module_by_name
from vibetuner.logging import LogLevel, logger, setup_logging


console = Console()


class AsyncTyper(typer.Typer):
    def __init__(self, *args, **kwargs):
        kwargs.setdefault("no_args_is_help", True)
        super().__init__(*args, **kwargs)

    @staticmethod
    def maybe_run_async(decorator, f):
        if inspect.iscoroutinefunction(f):

            @wraps(f)
            def runner(*args, **kwargs):
                return asyncer.runnify(f)(*args, **kwargs)

            decorator(runner)
        else:
            decorator(f)
        return f

    def callback(self, *args, **kwargs):
        decorator = super().callback(*args, **kwargs)
        return partial(self.maybe_run_async, decorator)

    def command(self, *args, **kwargs):
        decorator = super().command(*args, **kwargs)
        return partial(self.maybe_run_async, decorator)


def _get_app_help():
    try:
        from vibetuner.config import settings

        return f"{settings.project.project_name.title()} CLI"
    except (RuntimeError, ImportError):
        return "Vibetuner CLI"


app = AsyncTyper(help=_get_app_help())

LOG_LEVEL_OPTION = typer.Option(
    LogLevel.INFO,
    "--log-level",
    "-l",
    case_sensitive=False,
    help="Set the logging level",
)


@app.callback()
def callback(log_level: LogLevel | None = LOG_LEVEL_OPTION) -> None:
    """Initialize logging and other global settings."""
    setup_logging(level=log_level)


@app.command()
def version(
    show_app: bool = typer.Option(
        False,
        "--app",
        "-a",
        help="Show app settings version even if not in a project directory",
    ),
) -> None:
    """Show version information."""
    try:
        # Get vibetuner package version
        vibetuner_version = importlib.metadata.version("vibetuner")
    except importlib.metadata.PackageNotFoundError:
        vibetuner_version = "unknown"

    # Create table for nice display
    table = Table(title="Version Information")
    table.add_column("Component", style="cyan", no_wrap=True)
    table.add_column("Version", style="green", no_wrap=True)

    # Always show vibetuner package version
    table.add_row("vibetuner package", vibetuner_version)

    # Show app version if requested or if in a project
    try:
        from vibetuner.config import CoreConfiguration

        settings = CoreConfiguration()
        table.add_row(f"{settings.project.project_name} settings", settings.version)
    except Exception:
        if show_app:
            table.add_row("app settings", "not in project directory")
        # else: don't show app version if not in project and not requested

    console.print(table)


app.add_typer(db_app, name="db")
app.add_typer(notify_app, name="notify")
app.add_typer(run_app, name="run")
app.add_typer(scaffold_app, name="scaffold")


try:
    import_module_by_name("cli")
except ModuleNotFoundError:
    logger.warning("No cli modules found. Skipping user CLI commands.")
