import os
from logging.config import fileConfig

from sqlalchemy import engine_from_config
from sqlalchemy import pool

from alembic import context

from zix.server import utils, database, models

# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
config = context.config

# Interpret the config file for Python logging.
# This line sets up loggers basically.
fileConfig(config.config_file_name)

x_args = context.get_x_argument()
stage = "local"
for arg in x_args:
    if arg.startswith("stage="):
        stage = arg[len("stage="):].strip().strip("'").strip('"')

print(f"stage: {stage}")
CURRENT_DIR =  os.path.join(os.getcwd())

engine = None

def get_engine():
    global engine
    if engine:
        return engine

    yml = config.get_main_option("zix.env_yml")
    if os.path.isfile(yml):
        utils.define_env_vars_from_yaml(yml, stage=stage)
    zix_config = utils.dynamic_import(CURRENT_DIR, "config")

    engine = database.get_engine(
        zix_config.DATABASE_URL,
        zix_config.DB_CONNECT_ARGS,
        zix_config.DB_ENGINE_KWARGS,
        )
    return engine

# add your model's MetaData object here
# for 'autogenerate' support
# from myapp import mymodel
# target_metadata = mymodel.Base.metadata

# plugins = utils.import_submodules(CURRENT_DIR, "plugins")
# plugins = utils.list_submodules(plugins)

plugins = [x for x in os.listdir("plugins") if os.path.isdir(os.path.join("plugins", x))]

model_sets = []
engine = get_engine()

target_metadata = models.Base.metadata
models.Base.metadata.reflect(bind=engine)

for key in plugins:
    path = os.path.join(CURRENT_DIR, "plugins", key)
    if (key.startswith("_") or
        os.path.isfile(os.path.join(path, ".zixignore")) or
        not os.path.isfile(os.path.join(path, "models.py"))):
        continue
    # First import plugin submodule

    print(f"Loading {key}")
    m = utils.dynamic_import(os.path.join(CURRENT_DIR, "plugins"), key + ".models", root_package=True)
    model_sets.append(m)

# other values from the config, defined by the needs of env.py,
# can be acquired:
# my_important_option = config.get_main_option("my_important_option")
# ... etc.


def run_migrations_offline():
    """Run migrations in 'offline' mode.

    This configures the context with just a URL
    and not an Engine, though an Engine is acceptable
    here as well.  By skipping the Engine creation
    we don't even need a DBAPI to be available.

    Calls to context.execute() here emit the given string to the
    script output.

    """
    url = config.get_main_option("sqlalchemy.url")
    context.configure(
        url=url,
        target_metadata=target_metadata,
        literal_binds=True,
        dialect_opts={"paramstyle": "named"},
        # render_as_batch=True,
    )

    with context.begin_transaction():
        context.run_migrations()


def run_migrations_online():
    """Run migrations in 'online' mode.

    In this scenario we need to create an Engine
    and associate a connection with the context.

    """
    """
    connectable = engine_from_config(
        config.get_section(config.config_ini_section),
        prefix="sqlalchemy.",
        poolclass=pool.NullPool,
    )
    """
    connectable = get_engine()

    with connectable.connect() as connection:
        context.configure(
            connection=connection, target_metadata=target_metadata
        )

        with context.begin_transaction() as trx:
            context.run_migrations()
            if 'dry-run' in context.get_x_argument():
                print('Dry-run succeeded; now rolling back transaction...')
                trx.rollback()


if context.is_offline_mode():
    run_migrations_offline()
else:
    run_migrations_online()
