"""Shared pytest fixtures for pipeline/core/tests/.

Consolidates per-file duplicate registry-reset fixtures so a single
autouse fixture clears the dispatch registry (and, where applicable, the
bootstrap memo + provider env vars) before and after each test in this
subtree. Test files with substantively different fixture bodies retain
their local definitions, which override the conftest version under
pytest's closest-scope rule.
"""

from __future__ import annotations

import sys
import pathlib

# Make sure the recoil + pipeline import roots are on sys.path before we
# import any pipeline.core symbol — mirrors the bootstrap each test file
# performs at module level.
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent.parent.parent.parent))
# This directory itself, so the sibling `_test_paths_support` helper imports
# by bare module name from this conftest.
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent))
from recoil.core.paths import ensure_pipeline_importable  # noqa: E402

ensure_pipeline_importable()

import pytest  # noqa: E402

from recoil.pipeline.core.dispatch import _reset_bootstrap_for_tests  # noqa: E402
from recoil.pipeline.core.eval import _reset_eval_registry_for_tests  # noqa: E402
from recoil.pipeline.core.registry import _reset_for_tests  # noqa: E402

from _test_paths_support import install_shims, set_basetemp  # noqa: E402


@pytest.fixture(autouse=True)
def recoil_data_root_sentinel(tmp_path_factory):
    """REC-18: make a test's tmp projects-root look like the real data root.

    Tests in this subtree point the engine at a pytest tmp dir via
    ``monkeypatch.setenv("RECOIL_PROJECTS_ROOT", ...)``. The production path
    SSOT requires that root to (1) carry a ``.recoil-data-root`` sentinel
    (Law-4 fail-loud guard) and (2) contain a directory per project. Bare
    tmp dirs satisfy neither, so the guards (which stay ACTIVE in production)
    fire and the test errors before reaching its assertions.

    The shims fabricate the sentinel + project dirs ONLY for roots that live
    under pytest's session basetemp — production roots flow through the real
    guards unchanged, and the Law-4 assertion itself is never patched.
    """
    set_basetemp(tmp_path_factory.getbasetemp())
    install_shims()
    yield


@pytest.fixture(autouse=True)
def poc_start_frame_stub():
    """REC-18: the CP-6/CP-7 keyframe→video POC tests use a stub StepRunner
    whose keyframe step reports ``output_path="/tmp/poc.png"``, then feed that
    literal as the video step's ``start_frame``. The dispatch boundary's
    ``_validate_payload`` (Bug-C guard, 2026-05-19) requires a video_i2v
    ``start_frame`` to EXIST on disk — a real production check that should stay
    active. This writes a valid PNG-header stub at that exact path so the POC
    tests exercise the success path; it's a no-op for every other test (none
    read it). Cleaned up if this fixture created it.
    """
    import pathlib

    poc_png = pathlib.Path("/tmp/poc.png")
    created = not poc_png.exists()
    if created:
        poc_png.write_bytes(b"\x89PNG\r\n\x1a\n")  # minimal PNG magic header
    yield
    if created:
        poc_png.unlink(missing_ok=True)


@pytest.fixture(autouse=True)
def reset_registry():
    """Clear the dispatch registry before and after each test."""
    _reset_for_tests()
    yield
    _reset_for_tests()


@pytest.fixture(autouse=True)
def reset_registry_and_env(monkeypatch):
    """Clear dispatch registry + bootstrap memo, set provider env vars.

    Defaults match the audio_lipsync_* integration test files (both
    ELEVENLABS_API_KEY and SYNC_SO_API_KEY set). Test files that need a
    different env-var configuration (e.g. only one key, no bootstrap
    reset) define their own `reset_registry_and_env` fixture locally —
    pytest's closest-scope rule means the local definition wins.

    Footgun: this fixture is autouse across the entire pipeline/core/tests
    subtree, so EVERY test in this subtree sees ELEVENLABS_API_KEY and
    SYNC_SO_API_KEY set. Tests that assert "raises AuthError when key is
    unset" must explicitly call ``monkeypatch.delenv(...)`` in the test
    body (see test_audio_provider_elevenlabs.py and
    test_lipsync_provider_sync_so.py for the pattern).
    """
    _reset_for_tests()
    _reset_bootstrap_for_tests()
    monkeypatch.setenv("ELEVENLABS_API_KEY", "test-key-abc")
    monkeypatch.setenv("SYNC_SO_API_KEY", "test-syncso-key")
    yield
    _reset_for_tests()
    _reset_bootstrap_for_tests()


@pytest.fixture(autouse=True)
def reset_eval_registry():
    """Clear the eval-node registry before and after each test."""
    _reset_eval_registry_for_tests()
    yield
    _reset_eval_registry_for_tests()
