"""Save/restore monkey-patch registry."""

from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from caliper._config import BaseConfig

_originals: list[tuple[object, str, object]] = []


def save_and_patch(obj: object, attr: str, replacement: object) -> None:
    """Save the original attribute and replace it with the wrapper."""
    original = getattr(obj, attr)
    _originals.append((obj, attr, original))
    setattr(obj, attr, replacement)


def get_original(obj: object, attr: str) -> object:
    """Look up the saved original for a (obj, attr) pair."""
    for saved_obj, saved_attr, original in _originals:
        if saved_obj is obj and saved_attr == attr:
            return original
    raise LookupError(f"No saved original for {obj!r}.{attr}")


def unpatch_all() -> None:
    """Restore all originals in reverse order."""
    while _originals:
        obj, attr, original = _originals.pop()
        setattr(obj, attr, original)


def patch_all(config: BaseConfig) -> None:
    """Apply all provider patches. Deferred imports to avoid circular dependencies."""
    if config.patch_anthropic:
        try:
            from caliper._anthropic import patch

            patch()
        except ImportError:
            pass

    if config.patch_openai:
        try:
            from caliper._openai import patch as patch_openai

            patch_openai()
        except ImportError:
            pass
