"""
SQLAlchemy database setup with async support
"""
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
from sqlalchemy.orm import DeclarativeBase
from config import settings
import structlog

logger = structlog.get_logger()

# Create async engine
engine = create_async_engine(
    settings.DATABASE_URL,
    echo=settings.ENVIRONMENT == "development",
    pool_size=settings.DATABASE_POOL_SIZE,
    max_overflow=settings.DATABASE_MAX_OVERFLOW,
    pool_pre_ping=True,  # Verify connections before using
)

# Create async session factory
AsyncSessionLocal = async_sessionmaker(
    engine,
    class_=AsyncSession,
    expire_on_commit=False,
)

# Base class for models
class Base(DeclarativeBase):
    """Base class for all database models"""
    pass

# Dependency for FastAPI routes
async def get_db() -> AsyncSession:
    """
    Dependency that provides database session to FastAPI routes
    Usage: db: AsyncSession = Depends(get_db)
    """
    async with AsyncSessionLocal() as session:
        try:
            yield session
            await session.commit()
        except Exception:
            await session.rollback()
            raise
        finally:
            await session.close()

# Database initialization
async def init_db():
    """Initialize database connection (call on startup)"""
    try:
        logger.info("database_init", url=settings.DATABASE_URL.split("@")[-1])  # Hide credentials
        async with engine.begin() as conn:
            # Test connection
            await conn.run_sync(lambda _: None)
        logger.info("database_connected")
    except Exception as e:
        logger.error("database_connection_failed", error=str(e))
        raise

async def close_db():
    """Close database connections (call on shutdown)"""
    try:
        logger.info("database_closing")
        await engine.dispose()
        logger.info("database_closed")
    except Exception as e:
        logger.error("database_close_failed", error=str(e))
        raise
