"""ASV benchmarks for audit subscriber retry in get_container().

Measures the performance impact of the retry mechanism introduced by
bug #992: ``get_container()`` now retries ``audit_event_subscriber()``
on every call until it succeeds instead of permanently caching the
failure.
"""

from __future__ import annotations

import os
import sys
from pathlib import Path

try:
    from cleveragents.application import container as container_module
    from cleveragents.application.container import get_container, reset_container
except ModuleNotFoundError:
    sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
    from cleveragents.application import container as container_module
    from cleveragents.application.container import get_container, reset_container


class TimeGetContainerWithSuccessfulAudit:
    """Benchmark get_container() when audit subscriber succeeds immediately."""

    timeout = 60

    def setup(self) -> None:
        os.environ["CLEVERAGENTS_DATABASE_URL"] = "sqlite:///:memory:"
        reset_container()

    def time_get_container_first_call(self) -> None:
        reset_container()
        get_container()

    def time_get_container_cached(self) -> None:
        get_container()

    def teardown(self) -> None:
        reset_container()
        os.environ.pop("CLEVERAGENTS_DATABASE_URL", None)


class TimeGetContainerRetryAfterFailure:
    """Benchmark get_container() retry path after audit init failure."""

    timeout = 60

    def setup(self) -> None:
        os.environ["CLEVERAGENTS_DATABASE_URL"] = "sqlite:///:memory:"
        reset_container()

        class _FailOnceContainer:
            def __init__(self) -> None:
                self._attempts = 0

            def audit_event_subscriber(self) -> object:
                self._attempts += 1
                if self._attempts == 1:
                    raise RuntimeError("database not ready")
                return object()

        self._original_cls = container_module.Container
        container_module.Container = _FailOnceContainer  # type: ignore[assignment]

    def time_retry_after_failure(self) -> None:
        reset_container()
        get_container()  # first call — audit fails
        get_container()  # second call — audit retried and succeeds

    def teardown(self) -> None:
        container_module.Container = self._original_cls  # type: ignore[assignment]
        reset_container()
        os.environ.pop("CLEVERAGENTS_DATABASE_URL", None)
