"""CP-4 Phase 6 — module-load registration wiring tests."""

import sys
import pathlib
import importlib

sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent.parent.parent.parent))
from recoil.core.paths import ensure_pipeline_importable  # noqa: E402

ensure_pipeline_importable()

import pytest  # noqa: E402

from recoil.pipeline.core.registry import (  # noqa: E402
    is_registered,
    list_modalities,
    get_runner,
    _reset_for_tests,
)


@pytest.fixture(autouse=True)
def reset_registry_and_reimport():
    """Reset registry then reimport the runners package to retrigger
    the side-effect registration."""
    _reset_for_tests()
    if "recoil.pipeline.core.runners" in sys.modules:
        importlib.reload(sys.modules["recoil.pipeline.core.runners"])
    elif "pipeline.core.runners" in sys.modules:
        importlib.reload(sys.modules["pipeline.core.runners"])
    else:
        import recoil.pipeline.core.runners  # noqa: F401
    yield
    _reset_for_tests()


def test_stubs_register_at_import_time():
    """audio_t2a + lipsync_post are registered automatically by importing
    pipeline.core.runners."""
    assert is_registered("audio_t2a")
    assert is_registered("lipsync_post")


def test_live_runners_NOT_registered_without_bootstrap():
    """image_t2i + video_i2v require register_default_runners(step_runner) —
    they are NOT auto-registered by import alone."""
    assert not is_registered("image_t2i")
    assert not is_registered("video_i2v")


def test_register_default_runners_registers_live():
    from recoil.pipeline.core.dispatch import register_default_runners

    class _FakeSR:
        def execute_keyframe(self, **k):
            return None

        def execute_video(self, **k):
            return None

    register_default_runners(_FakeSR())
    assert is_registered("image_t2i")
    assert is_registered("video_i2v")


def test_register_default_runners_idempotent():
    from recoil.pipeline.core.dispatch import register_default_runners

    class _FakeSR:
        def execute_keyframe(self, **k):
            return None

        def execute_video(self, **k):
            return None

    sr = _FakeSR()
    register_default_runners(sr)
    register_default_runners(sr)
    assert is_registered("image_t2i")
    assert is_registered("video_i2v")


def test_register_default_runners_rejects_none():
    from recoil.pipeline.core.dispatch import register_default_runners

    with pytest.raises(ValueError):
        register_default_runners(None)


def test_full_registration_yields_four_modalities():
    from recoil.pipeline.core.dispatch import register_default_runners

    class _FakeSR:
        def execute_keyframe(self, **k):
            return None

        def execute_video(self, **k):
            return None

    register_default_runners(_FakeSR())
    mods = list_modalities()
    assert set(mods) >= {"image_t2i", "video_i2v", "audio_t2a", "lipsync_post"}


def test_get_runner_audio_returns_real_runner():
    """Post-CP-8: AudioRunner is a real runner. Empty payload returns a
    failure-RunResult (NEVER raises), reporting missing required keys."""
    runner = get_runner("audio_t2a")
    result = runner.run({})
    assert result.success is False
    assert result.error is not None
    for key in ("shot_id", "text", "voice_id", "model"):
        assert key in result.error


def test_get_runner_lipsync_returns_real_runner():
    """Post-CP-8: LipSyncPostProcessor is a real runner. Empty payload returns
    a failure-RunResult (NEVER raises), reporting missing required keys."""
    runner = get_runner("lipsync_post")
    result = runner.run({})
    assert result.success is False
    assert result.error is not None
    for key in ("shot_id", "video_path", "audio_path", "model"):
        assert key in result.error


def test_get_runner_image_t2i_keyerror_lists_bootstrap():
    """When image_t2i is unregistered, the KeyError message hints at
    the bootstrap call (`register_default_runners`)."""
    with pytest.raises(KeyError) as exc:
        get_runner("image_t2i")
    msg = str(exc.value)
    assert "image_t2i" in msg
    assert "register_default_runners" in msg, (
        f"Bootstrap hint missing from KeyError message: {msg!r}"
    )


def test_get_runner_video_i2v_keyerror_lists_bootstrap():
    """video_i2v gets the same bootstrap hint as image_t2i."""
    with pytest.raises(KeyError) as exc:
        get_runner("video_i2v")
    assert "register_default_runners" in str(exc.value)


def test_get_runner_unknown_modality_no_bootstrap_hint():
    """Stubs / unknown modalities don't suggest bootstrap (irrelevant)."""
    with pytest.raises(KeyError) as exc:
        get_runner("totally_made_up_modality")
    assert "register_default_runners" not in str(exc.value)
