import asyncio
from logging.config import fileConfig

from sqlalchemy import pool
from sqlalchemy.engine import Connection
from sqlalchemy.ext.asyncio import async_engine_from_config

from alembic import context

# Import your models
from app.core.database import Base
from app.models import User, Team, Tree, Session, Attachment, InviteCode
from app.models.email_verification_token import EmailVerificationToken
from app.models.tree_embedding import TreeEmbedding
from app.models.copilot_conversation import CopilotConversation
from app.models.assistant_chat import AssistantChat
from app.models.survey_response import SurveyResponse
from app.models.survey_invite import SurveyInvite
from app.models.ai_suggestion import AISuggestion  # noqa: F401
from app.models.kb_import import KBImport, KBImportNode  # noqa: F401
from app.models.script_template import ScriptCategory, ScriptTemplate, ScriptGeneration  # noqa: F401
from app.models.psa_connection import PsaConnection  # noqa: F401
from app.models.ai_session import AISession  # noqa: F401
from app.models.ai_session_step import AISessionStep  # noqa: F401
from app.models.psa_post_log import PsaPostLog  # noqa: F401
from app.models.psa_member_mapping import PsaMemberMapping  # noqa: F401
from app.models.script_builder_session import ScriptBuilderSession, ScriptBuilderMessage  # noqa: F401
from app.models.session_branch import SessionBranch  # noqa: F401
from app.models.fork_point import ForkPoint  # noqa: F401
from app.models.session_handoff import SessionHandoff  # noqa: F401
from app.models.session_resolution_output import SessionResolutionOutput  # noqa: F401

from app.core.config import settings


def _alembic_sync_url() -> str:
    """Return a psycopg2-compatible sync URL for Alembic.

    Priority order:
    1. DATABASE_URL_SYNC — in Railway this is set as a reference variable
       (${{pgvector.DATABASE_URL}}) that resolves to the correct postgres
       superuser credentials for the current environment (production, PR preview,
       etc.). This always works even on fresh databases before any custom roles
       have been created, because it uses the postgres superuser.
    2. ADMIN_DATABASE_URL (resolutionflow_admin, BYPASSRLS) converted to a sync
       driver — fallback for local dev where DATABASE_URL_SYNC may not be set.
    """
    if settings.DATABASE_URL_SYNC:
        return settings.DATABASE_URL_SYNC

    admin_url = settings.ADMIN_DATABASE_URL
    if admin_url and "+asyncpg" in admin_url:
        return admin_url.replace("postgresql+asyncpg://", "postgresql://")

    return settings.DATABASE_URL_SYNC


# this is the Alembic Config object
config = context.config

# Override sqlalchemy.url with the sync version for migrations
config.set_main_option("sqlalchemy.url", _alembic_sync_url())

# Interpret the config file for Python logging.
if config.config_file_name is not None:
    fileConfig(config.config_file_name)

# add your model's MetaData object here
target_metadata = Base.metadata


def run_migrations_offline() -> None:
    """Run migrations in 'offline' mode."""
    url = config.get_main_option("sqlalchemy.url")
    context.configure(
        url=url,
        target_metadata=target_metadata,
        literal_binds=True,
        dialect_opts={"paramstyle": "named"},
    )

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


def do_run_migrations(connection: Connection) -> None:
    context.configure(connection=connection, target_metadata=target_metadata)

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


async def run_async_migrations() -> None:
    """Run migrations in 'online' mode with async engine."""
    from sqlalchemy.ext.asyncio import create_async_engine

    connectable = create_async_engine(
        settings.DATABASE_URL,
        poolclass=pool.NullPool,
    )

    async with connectable.connect() as connection:
        await connection.run_sync(do_run_migrations)

    await connectable.dispose()


def run_migrations_online() -> None:
    """Run migrations in 'online' mode."""
    from sqlalchemy import create_engine

    connectable = create_engine(
        _alembic_sync_url(),
        poolclass=pool.NullPool,
    )

    with connectable.connect() as connection:
        do_run_migrations(connection)


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