"""Helper script for tdd_automation_profile_di_bypass.robot smoke tests.

Each subcommand exercises ``_get_service()`` from
``cleveragents.cli.commands.automation_profile`` to verify that it
delegates to the DI container rather than manually constructing the
persistence layer with ``create_engine`` / ``sessionmaker``.

Bug #990 was fixed by PR #1181. These helpers report pass (exit 0 + sentinel)
when the DI delegation is correct, and fail (exit 1) when the bug regresses.
"""

from __future__ import annotations

import sys
from collections.abc import Callable
from pathlib import Path
from typing import Any
from unittest.mock import MagicMock, patch

# Ensure local source tree is importable.
_ROOT = Path(__file__).resolve().parents[1]
_SRC = str(_ROOT / "src")
if _SRC not in sys.path:
    sys.path.insert(0, _SRC)

_PATCH_GET_CONTAINER = "cleveragents.application.container.get_container"
_PATCH_CREATE_ENGINE = "sqlalchemy.create_engine"
_PATCH_SESSIONMAKER = "sqlalchemy.orm.sessionmaker"


# ---------------------------------------------------------------------------
# Subcommands
# ---------------------------------------------------------------------------


def container_resolution() -> None:
    """Verify _get_service() returns the container's automation_profile_service.

    Exits 0 with sentinel when the DI container is correctly used (bug fixed).
    Exits 1 when _get_service() does not delegate to the container (bug regressed).
    """
    from cleveragents.cli.commands.automation_profile import _get_service

    mock_service: MagicMock = MagicMock(name="MockAutomationProfileService")
    mock_container: MagicMock = MagicMock(name="MockContainer")
    mock_container.automation_profile_service.return_value = mock_service

    with patch(_PATCH_GET_CONTAINER, return_value=mock_container):
        result: Any = _get_service()

    if result is not mock_service:
        print(
            f"_get_service() returned {type(result)!r} instead of the "
            "container service. Bug #990 regression: not delegating to DI container.",
            file=sys.stderr,
        )
        sys.exit(1)

    print("tdd-ap990-container-resolution-ok")


def di_bypass() -> None:
    """Verify _get_service() does not call create_engine or sessionmaker directly.

    Exits 0 with sentinel when neither is called (bug fixed).
    Exits 1 with an explanation when either is called (bug regressed).
    """
    from cleveragents.cli.commands.automation_profile import _get_service

    create_engine_mock: MagicMock = MagicMock(name="MockCreateEngine")
    sessionmaker_mock: MagicMock = MagicMock(name="MockSessionmaker")

    mock_service: MagicMock = MagicMock(name="MockAutomationProfileService")
    mock_container: MagicMock = MagicMock(name="MockContainer")
    mock_container.automation_profile_service.return_value = mock_service

    with (
        patch(_PATCH_CREATE_ENGINE, create_engine_mock),
        patch(_PATCH_SESSIONMAKER, sessionmaker_mock),
        patch(_PATCH_GET_CONTAINER, return_value=mock_container),
    ):
        _get_service()

    if create_engine_mock.called:
        print(
            f"Bug #990 regression: _get_service() called create_engine() directly "
            f"({create_engine_mock.call_count} time(s)) instead of delegating to "
            "container.automation_profile_service().",
            file=sys.stderr,
        )
        sys.exit(1)

    if sessionmaker_mock.called:
        print(
            f"Bug #990 regression: _get_service() called sessionmaker() directly "
            f"({sessionmaker_mock.call_count} time(s)) instead of delegating to "
            "container.automation_profile_service().",
            file=sys.stderr,
        )
        sys.exit(1)

    print("tdd-ap990-di-bypass-ok")


# ---------------------------------------------------------------------------
# Dispatcher
# ---------------------------------------------------------------------------

_COMMANDS: dict[str, Callable[[], None]] = {
    "container-resolution": container_resolution,
    "di-bypass": di_bypass,
}

if __name__ == "__main__":
    if len(sys.argv) < 2 or sys.argv[1] not in _COMMANDS:
        print(
            f"Usage: {sys.argv[0]} <{'|'.join(_COMMANDS)}>",
            file=sys.stderr,
        )
        sys.exit(1)
    _COMMANDS[sys.argv[1]]()
