import os
from functools import lru_cache
from typing import Optional

from sqlalchemy import create_engine
from sqlalchemy.engine import Engine


def _default_db_path() -> str:
    env_path = os.getenv("SYNTHNEURA_DB_PATH")
    if env_path:
        return env_path
    repo_root = os.path.abspath(
        os.path.join(os.path.dirname(__file__), "..", "..", "..")
    )
    return os.path.join(repo_root, "trials.db")


def resolve_db_url(db_url: Optional[str] = None) -> str:
    """
    Resolve a database URL for SQLAlchemy.

    If SYNTHNEURA_DB_URL is set, use it. Otherwise, fall back to a local
    SQLite file path (SYNTHNEURA_DB_PATH or trials.db).
    """

    env_url = os.getenv("SYNTHNEURA_DB_URL")
    if env_url:
        return env_url
    if db_url and "://" in db_url:
        return db_url
    path = db_url or _default_db_path()
    if "://" in path:
        return path
    abs_path = os.path.abspath(path)
    return f"sqlite:///{abs_path}"


@lru_cache(maxsize=8)
def _engine_for(db_url: str) -> Engine:
    connect_args = {}
    if db_url.startswith("sqlite"):
        connect_args = {"check_same_thread": False}
    return create_engine(
        db_url, future=True, pool_pre_ping=True, connect_args=connect_args
    )


def get_engine(db_url: Optional[str] = None) -> Engine:
    """
    Return a cached SQLAlchemy engine for the resolved database URL.
    """

    resolved = resolve_db_url(db_url)
    return _engine_for(resolved)
