from __future__ import annotations

from pathlib import Path
from typing import Callable

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

from .models import Base


def create_sqlite_engine(db: str):
    """
    Construct an Engine for a SQLite database.

    Accepts either a plain file path or a full SQLAlchemy URL.
    """
    if "://" not in db:
        path = Path(db)
        path.touch()
        url = f"sqlite:///{path.resolve()}"
    else:
        url = db
    engine = create_engine(url, future=True)
    return engine


def init_schema(engine) -> None:
    """
    Create tables and indexes defined in models.Base.
    """
    Base.metadata.create_all(engine)


def make_session_factory(engine) -> sessionmaker[Session]:
    """
    Return a configured sessionmaker.
    """
    return sessionmaker(bind=engine, autoflush=False, autocommit=False, future=True)


def get_session_factory(db: str) -> sessionmaker[Session]:
    """
    High-level entry point:

    - create engine from `db`
    - create all tables (idempotent)
    - return a sessionmaker bound to that engine
    """
    engine = create_sqlite_engine(db)
    init_schema(engine)
    return make_session_factory(engine)
