from logging.config import fileConfig
from fnmatch import fnmatch
import sys
from pathlib import Path

from sqlalchemy import engine_from_config
from sqlalchemy import pool, text, exc

from alembic import context

import yaml
config = context.config
if config.config_file_name is not None:
    fileConfig(config.config_file_name)

sys.path.insert(0, str(Path(__file__).resolve().parent.parent.parent.parent))

from setup import DATABASE, app, DB_SESSION
from config import CONFIG, merge_yaml
from main.models.logs.event import Event

target_metadata = DATABASE.metadata

def include_object(_, name, type_, __, ___):
    if type_ == "table":
        for exclude in context.config.get_section('alembic:exclude')['tables'].split(','):
            if fnmatch(name, exclude):
                return False
    return True

def run_migrations() -> None:
    """Run migrations in 'online' mode.

    In this scenario we need to create an Engine
    and associate a connection with the context.
    """
    print(f"Running in {app.config['ENV']} mode")

    superuser = CONFIG.get('superuser')
    superuser_password = CONFIG.get('superuser_password')

    if not superuser or not superuser_password:
        raise ValueError("Please create superuser and superuser_password keys in your .env file")

    yaml_databases = []
    if app.config['ENV'] != 'test':
        yaml_databases.append(CONFIG['databases']['satbots'])

    if app.config['ENV'] in ['development', 'test']:
        # Also migrate test database
        with open(f"{app.root_path}/config.yml", 'r', encoding="utf-8") as config_file:
            test_config = merge_yaml(yaml.safe_load(config_file), env='test')
        yaml_databases.append(test_config['databases']['satbots'])

    databases = []
    for db in yaml_databases:
        host_port = '' if app.config['ENV'] == 'test' else f"@{db['host']}:{db['port']}"
        databases.append(f"postgresql://{superuser}:{superuser_password}{host_port}/{db['database']}")

    print(f"{app.config['ENV'].title()} databases to migrate: {len(databases)}")

    for database in databases:
        print("\n\n -", database.split('/')[-1])

        connectable = engine_from_config(
            config.get_section(config.config_ini_section, {}),
            url=database,
            prefix="sqlalchemy.",
            poolclass=pool.NullPool,
        )

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

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

run_migrations()
