from __future__ import annotations

from sqlalchemy import create_engine
from sqlalchemy.engine import Engine
from sqlalchemy.orm import Session, sessionmaker

from app.core.config import get_settings

_engine: Engine | None = None
_session_factory: sessionmaker[Session] | None = None


def configure_session_factory() -> None:
    global _engine, _session_factory

    settings = get_settings()

    if _engine is not None:
        _engine.dispose()

    engine_kwargs = {
        "echo": settings.sqlalchemy_echo,
        "pool_pre_ping": True,
    }
    if not settings.resolved_database_url.startswith("sqlite"):
        engine_kwargs.update(
            {
                "pool_size": max(1, int(settings.sqlalchemy_pool_size or 10)),
                "max_overflow": max(0, int(settings.sqlalchemy_max_overflow or 20)),
                "pool_timeout": max(1, int(settings.sqlalchemy_pool_timeout or 30)),
            }
        )

    _engine = create_engine(settings.resolved_database_url, **engine_kwargs)
    _session_factory = sessionmaker(bind=_engine, autoflush=False, autocommit=False)


def get_engine() -> Engine:
    global _engine

    if _engine is None:
        configure_session_factory()

    return _engine


def get_session_factory() -> sessionmaker[Session]:
    global _session_factory

    if _session_factory is None:
        configure_session_factory()

    return _session_factory
