"""Shared in-memory UnitOfWork factory for test isolation.

Provides ``build_test_uow`` — a factory that constructs an in-memory
SQLite-backed ``UnitOfWork`` suitable for both Behave step definitions
and Robot Framework integration test helpers.

Centralising the UoW construction eliminates duplication and ensures
both test suites exercise the same database setup.  Any changes to
``UnitOfWork.__init__`` must be reflected here in a single place rather
than in each consuming test file.

Used by:
- ``features/steps/plan_use_action_args_integrity_steps.py``
- ``robot/helper_plan_use_action_args_integrity.py``
"""

from __future__ import annotations

from typing import Any

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

from cleveragents.infrastructure.database.models import Base
from cleveragents.infrastructure.database.unit_of_work import UnitOfWork


def build_test_uow() -> tuple[UnitOfWork, sessionmaker[Session], Engine]:
    """Build an in-memory UoW for testing.

    Creates a fresh SQLite ``:memory:`` database with all tables, foreign
    key enforcement enabled, and a ``UnitOfWork`` instance that bypasses
    the constructor to avoid running migrations inside the test harness.

    Returns:
        A three-tuple of ``(uow, session_factory, engine)``.
    """
    engine = create_engine(
        "sqlite:///:memory:",
        echo=False,
        future=True,
        connect_args={"check_same_thread": False},
    )

    @event.listens_for(engine, "connect")
    def _enable_fk(dbapi_conn: Any, _rec: Any) -> None:
        cursor = dbapi_conn.cursor()
        cursor.execute("PRAGMA foreign_keys=ON")
        cursor.close()

    Base.metadata.create_all(engine)
    sf: sessionmaker[Session] = sessionmaker(
        bind=engine,
        expire_on_commit=False,
        autoflush=False,
        autocommit=False,
        class_=Session,
    )

    uow = UnitOfWork.__new__(UnitOfWork)
    # Keep these attributes in sync with UnitOfWork.__init__ — we bypass
    # the constructor to avoid running migrations inside the test harness.
    uow.database_url = "sqlite:///:memory:"
    uow._engine = engine
    uow._session_factory = sf
    uow._database_initialized = True
    uow._prompt_for_migration = None
    uow._require_confirmation = False

    return uow, sf, engine
