"""Engine + session factory. One engine per process, created lazily so tests can
point PUNCHLIST_DB_URL at a throwaway SQLite file before first use.

The kit's four tables live in this same database via bw_store_sqlalchemy
managed mode (see accounts.py), on the same Base.metadata — so Alembic owns
every table in the app, kit included.
"""

import functools

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

from app.config import get_settings


@functools.lru_cache
def get_engine():
    url = get_settings().database_url
    # pool_pre_ping heals connections dropped by a db restart under compose.
    kwargs = {"pool_pre_ping": True}
    if url.startswith("sqlite"):
        # timeout: the kit store opens its own connections to the same file;
        # without a busy timeout, an overlapping write shows up as
        # "database is locked" instead of briefly waiting.
        kwargs["connect_args"] = {"check_same_thread": False, "timeout": 15}
    return create_engine(url, **kwargs)


@functools.lru_cache
def get_session_factory():
    return sessionmaker(bind=get_engine(), expire_on_commit=False)
