from __future__ import annotations

import argparse

from cf_pipeline_engine import cli


class _Proc:
    def __init__(self, returncode: int = 0) -> None:
        self.returncode = returncode


def _make_args() -> argparse.Namespace:
    return argparse.Namespace(
        pipeline="demo.jsonld",
        steps=None,
        plugins=None,
        engine_threads=0,
        max_total_threads=None,
        default_step_threads=None,
        respect_step_parallelism=None,
        deterministic=None,
        interval=0.0,
        iterations=1,
        duration=0.0,
        debug=False,
        exe="cf_pipeline_v2",
    )


def test_direct_engine_blocked_by_default(monkeypatch) -> None:
    monkeypatch.delenv("CF_ALLOW_DIRECT_ENGINE", raising=False)
    monkeypatch.setattr(cli, "_discover_plugin_dirs", lambda: [])

    def _should_not_run(*args, **kwargs):  # noqa: ANN001, ANN002
        raise AssertionError("subprocess.run must not be called when policy blocks direct start")

    monkeypatch.setattr(cli.subprocess, "run", _should_not_run)
    code = cli._run_from_args(_make_args())
    assert code == 2


def test_direct_engine_allowed_with_override(monkeypatch) -> None:
    monkeypatch.setenv("CF_ALLOW_DIRECT_ENGINE", "1")
    monkeypatch.setattr(cli, "_discover_plugin_dirs", lambda: [])
    seen: dict[str, object] = {}

    def _fake_run(cmd, check=False):  # noqa: ANN001, ANN202
        seen["cmd"] = cmd
        seen["check"] = check
        return _Proc(0)

    monkeypatch.setattr(cli.subprocess, "run", _fake_run)
    code = cli._run_from_args(_make_args())

    assert code == 0
    assert seen["check"] is False
    assert isinstance(seen["cmd"], list)
    assert "--pipeline" in seen["cmd"]


def test_direct_engine_not_allowed_with_invocation_mode_only(monkeypatch) -> None:
    monkeypatch.delenv("CF_ALLOW_DIRECT_ENGINE", raising=False)
    monkeypatch.setenv("CF_PIPELINE_INVOCATION_MODE", "state-run-loop")
    monkeypatch.setattr(cli, "_discover_plugin_dirs", lambda: [])

    def _should_not_run(*args, **kwargs):  # noqa: ANN001, ANN002
        raise AssertionError("subprocess.run must not be called when only invocation mode is set")

    monkeypatch.setattr(cli.subprocess, "run", _should_not_run)
    code = cli._run_from_args(_make_args())
    assert code == 2


def test_unified_cli_default_modules_excludes_engine_wrapper(monkeypatch) -> None:
    try:
        from cf_cli.cli import DEFAULT_MODULES
    except Exception:
        return
    assert "cf_pipeline_engine.cli" not in DEFAULT_MODULES
