import importlib
import importlib.metadata
import logging
from argparse import ArgumentParser, Namespace
from pathlib import Path
from typing import Optional, Callable

from bagsy.database import USER_FOLDER, Database
from bagsy.logger import change_level

SetupParserFunc = Callable[[ArgumentParser], None]
ExecCmdFunc = Callable[[Database, Namespace, ArgumentParser], None]


def get_module_setup_parser(module: str) -> SetupParserFunc:
    module = importlib.import_module(f"{module}.__main__")
    return getattr(module, "setup_parser")


def get_module_exec_cmd(module: str) -> ExecCmdFunc:
    module = importlib.import_module(f"{module}.__main__")
    return getattr(module, "exec_cmd")


def get_version():
    try:
        return importlib.metadata.version('bagSy')
    except importlib.metadata.PackageNotFoundError:
        return "dev"


def parse_and_exec(module: str,
                   name: str, description: str,
                   cli_args: Optional[list[str]]):
    parser = ArgumentParser(
        prog=name,
        description=description,
        epilog=f"bagSy {get_version()}. To contribute see https://gitlab.ensta.fr/ssh/bagsy."
    )
    # declare arguments
    parser.add_argument("--config-path", type=Path, default=USER_FOLDER / "user.db",
                        help="The path of the sqlite database storing the local config.")
    parser.add_argument("--read-only", action="store_true",
                        help="If the database should be opened in read only mode.")
    parser.add_argument("--verbose", "-v", action="store_true",
                        help="If logger should be started in debug mode.")
    get_module_setup_parser(module)(parser)
    # parse arguments
    args = parser.parse_args(cli_args)
    # select logging level
    change_level(logging.DEBUG if args.verbose else logging.INFO)
    # connect database
    db = Database(args.config_path, args.read_only)
    # execute command
    get_module_exec_cmd(module)(db, args, parser)
