"""SQLite engine and session factory."""

from __future__ import annotations

from pathlib import Path

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

from luca_assistant.config import get_settings

_session_factory: sessionmaker[Session] | None = None
_session_factory_path: str | None = None


def _resolve_db_path(db_path: str | None) -> str:
    if db_path is None:
        db_path = get_settings().db.db_path
    return db_path


def get_engine(db_path: str | None = None):
    """Create SQLite engine."""
    db_path = _resolve_db_path(db_path)
    Path(db_path).parent.mkdir(parents=True, exist_ok=True)
    return create_engine(f"sqlite:///{db_path}", echo=False)


def get_session_factory(db_path: str | None = None) -> sessionmaker[Session]:
    """Get or create session factory. Recreates if an explicit db_path differs from cached one."""
    global _session_factory, _session_factory_path
    if _session_factory is not None and db_path is None:
        # No explicit path — reuse whatever factory we have (supports test patching)
        return _session_factory
    resolved = _resolve_db_path(db_path)
    if _session_factory is None or resolved != _session_factory_path:
        engine = get_engine(resolved)
        _session_factory = sessionmaker(bind=engine)
        _session_factory_path = resolved
    return _session_factory


def get_session(db_path: str | None = None) -> Session:
    """Get a new database session."""
    return get_session_factory(db_path)()


def init_db(db_path: str | None = None) -> None:
    """Create all tables (reuses the cached engine when paths match)."""
    from luca_assistant.db.models import Base

    resolved = _resolve_db_path(db_path)
    # Reuse the session factory's engine if it points to the same path
    factory = get_session_factory(resolved)
    engine = factory.kw["bind"]
    Base.metadata.create_all(engine)


def reset_session_factory() -> None:
    """Reset the session factory (useful for testing)."""
    global _session_factory, _session_factory_path
    _session_factory = None
    _session_factory_path = None
