import logging
from importlib import import_module
from typing import Union

from jcramda import loc

__all__ = [
    "connect",
    "conn",
    "init_engine",
]

__engines = dict()


def init_engine(tag: str, *args, create_engine=None, **kwargs):
    """Init a oracle engine

    :param tag: a flag with connection engine
    :param create_engine: a function create a database connection engine
    :param kwargs: database connection config

    **Options**
     * schema: default is 'oracle', can use ['oracle', 'mysql', 'sqlite', 'postgres', etc...]
     * user: database connection username
     * password: database connection password
     * dsn: database host and port dsn string
     * url: database connection url, like that: "oracle://username:password@10.0.0.5:1521/sid?encoding=utf-8

    :return:
    """
    schema = kwargs.get("schema", "oracle")
    if create_engine is None:
        sqlmodule = import_module("sqlalchemy")
        url = (
            "{schema}://{user}:{password}@{dsn}?encoding=utf-8".format(
                schema=schema,
                user=kwargs["user"],
                password=kwargs["password"],
                dsn=kwargs["dsn"],
            )
            if "url" not in kwargs
            else kwargs.pop("url")
        )
        current_engine = sqlmodule.create_engine(
            url, pool_size=10, encoding="utf-8", **kwargs
        )
    else:
        current_engine = create_engine(*args, **kwargs)
    __engines[tag] = current_engine
    return current_engine


def new_client(tag, *args, create_engine=None, **kwargs):
    if create_engine is None:
        try:
            module = import_module("sqlalchemy")
            create_engine = getattr(module, "create_engine")
        except ModuleNotFoundError as err:
            logging.error(err)

    __engines[tag] = create_engine(*args, **kwargs)
    return __engines[tag]


def get_client(name: Union[str, int] = 0):
    if len(__engines) > 0:
        return loc(name, __engines)
    raise RuntimeError("no any host can connect.")


def connect(n: Union[str, int] = 0):
    return get_client(n).connect()


def load(conf: dict):
    """
    一次性读取配置文件，生成数据库链接
    配置文件格式：dict(dbname="{dburl}")
    ```
    {
      "db1": "mysql://username:password@127.0.0.1:3306/dbname?encoding=utf8mb",
      "myoracle": "oracle://...",
    }
    ```
    @param conf: Dict[str, str]
    """
    if conf and len(conf) > 0:
        for key in conf:
            try:
                init_engine(key, url=conf[key])
            except Exception as err:
                logging.warning(f"load database [{key}] failed: {err}")
            # print(f'database [{key}] connected')


conn = connect


def instances():
    return [*__engines.keys()]
