"""ASV benchmarks for service-level retry patterns.

Measures the overhead of retry_service_operation decorator
and retry_auto_debug happy-path latency.
"""

from __future__ import annotations

import asyncio
from typing import Any

from cleveragents.core.circuit_breaker import CircuitBreaker
from cleveragents.core.retry_service_patterns import (
    RetryContext,
    is_read_only_plan_operation,
    retry_auto_debug,
    retry_service_operation,
)


class RetryServiceOperationDecoratorBench:
    """Benchmark retry_service_operation decorator overhead."""

    timeout = 60

    def time_decorator_construction_sync(self) -> None:
        """Benchmark constructing sync service retry decorator."""

        @retry_service_operation(
            service_name="test_service",
            operation_name="test_op",
            max_attempts=3,
        )
        def dummy_func() -> str:
            return "success"

    def time_decorator_construction_async(self) -> None:
        """Benchmark constructing async service retry decorator."""

        @retry_service_operation(
            service_name="test_service",
            operation_name="test_op",
            max_attempts=3,
        )
        async def dummy_func() -> str:
            return "success"

    def time_decorator_with_circuit_breaker(self) -> None:
        """Benchmark decorator with circuit breaker instance."""
        cb = CircuitBreaker(
            failure_threshold=5,
            recovery_timeout=60.0,
            name="test_service",
        )

        @retry_service_operation(
            service_name="test_service",
            operation_name="test_op",
            max_attempts=3,
            circuit_breaker=cb,
        )
        def dummy_func() -> str:
            return "success"

    def time_decorator_with_exponential_strategy(self) -> None:
        """Benchmark decorator with exponential backoff strategy."""

        @retry_service_operation(
            service_name="test_service",
            operation_name="test_op",
            max_attempts=3,
            backoff_strategy="exponential",
            base_delay=1.0,
            max_delay=60.0,
        )
        def dummy_func() -> str:
            return "success"


class RetryServiceOperationInvocationBench:
    """Benchmark happy-path service retry invocation."""

    timeout = 60

    def setup(self) -> None:
        """Set up decorated service operations."""

        @retry_service_operation(
            service_name="test_service",
            operation_name="test_op",
            max_attempts=3,
        )
        def sync_op() -> str:
            return "success"

        @retry_service_operation(
            service_name="test_service",
            operation_name="test_op",
            max_attempts=3,
        )
        async def async_op() -> str:
            return "success"

        cb = CircuitBreaker(
            failure_threshold=5,
            recovery_timeout=60.0,
            name="test_service",
        )

        @retry_service_operation(
            service_name="test_service",
            operation_name="test_op",
            max_attempts=3,
            circuit_breaker=cb,
        )
        def breaker_op() -> str:
            return "success"

        self.sync_op = sync_op
        self.async_op = async_op
        self.breaker_op = breaker_op

    def time_sync_operation_invocation(self) -> None:
        """Benchmark sync service operation invocation (happy path)."""
        self.sync_op()

    def time_async_operation_invocation(self) -> None:
        """Benchmark async service operation invocation (happy path)."""
        asyncio.run(self.async_op())

    def time_operation_with_circuit_breaker(self) -> None:
        """Benchmark service operation with circuit breaker (happy path)."""
        self.breaker_op()


class RetryServiceOperationWithArgumentsBench:
    """Benchmark service retry with function arguments."""

    timeout = 60

    def setup(self) -> None:
        """Set up decorated operations with arguments."""

        @retry_service_operation(
            service_name="test_service",
            operation_name="fetch_data",
            max_attempts=3,
        )
        def fetch_data(
            resource_id: int, include_metadata: bool = False
        ) -> dict[str, Any]:
            return {"id": resource_id, "data": "test"}

        @retry_service_operation(
            service_name="test_service",
            operation_name="update_data",
            max_attempts=3,
        )
        async def update_data(
            resource_id: int, payload: dict[str, Any]
        ) -> dict[str, Any]:
            return {"id": resource_id, "updated": True}

        self.fetch_data = fetch_data
        self.update_data = update_data

    def time_sync_with_positional_args(self) -> None:
        """Benchmark sync operation with positional arguments."""
        self.fetch_data(42, True)

    def time_sync_with_keyword_args(self) -> None:
        """Benchmark sync operation with keyword arguments."""
        self.fetch_data(resource_id=42, include_metadata=True)

    def time_async_with_complex_payload(self) -> None:
        """Benchmark async operation with complex payload."""
        payload = {"key": "value", "nested": {"data": [1, 2, 3]}}
        asyncio.run(self.update_data(42, payload))


class RetryAutoDebugBench:
    """Benchmark retry_auto_debug decorator."""

    timeout = 60

    def time_auto_debug_construction(self) -> None:
        """Benchmark constructing auto-debug decorator."""

        @retry_auto_debug(max_debug_attempts=3)
        async def dummy_func() -> str:
            return "success"

    def time_auto_debug_invocation(self) -> None:
        """Benchmark auto-debug invocation (happy path)."""

        @retry_auto_debug(max_debug_attempts=3)
        async def dummy_func() -> str:
            return "success"

        asyncio.run(dummy_func())

    def time_auto_debug_single_attempt(self) -> None:
        """Benchmark auto-debug with single attempt."""

        @retry_auto_debug(max_debug_attempts=1)
        async def dummy_func() -> str:
            return "success"

        asyncio.run(dummy_func())

    def time_auto_debug_multiple_attempts(self) -> None:
        """Benchmark auto-debug with multiple attempts configured."""

        @retry_auto_debug(max_debug_attempts=5)
        async def dummy_func() -> str:
            return "success"

        asyncio.run(dummy_func())


class RetryContextBench:
    """Benchmark RetryContext operations."""

    timeout = 60

    def time_context_creation(self) -> None:
        """Benchmark creating a retry context."""
        RetryContext(
            operation_name="test_op",
            max_attempts=3,
        )

    def time_context_with_custom_wait(self) -> None:
        """Benchmark context with custom wait strategy."""
        from tenacity import wait_exponential

        RetryContext(
            operation_name="test_op",
            max_attempts=3,
            wait_strategy=wait_exponential(multiplier=1, min=1, max=30),
        )

    def time_context_property_access(self) -> None:
        """Benchmark accessing context properties."""
        ctx = RetryContext(
            operation_name="test_op",
            max_attempts=3,
        )
        _ = ctx.operation_name
        _ = ctx.max_attempts
        _ = ctx.attempt_count

    def time_context_execute(self) -> None:
        """Benchmark executing a function via RetryContext."""
        ctx = RetryContext(
            operation_name="test_op",
            max_attempts=3,
        )
        ctx.execute(lambda: "success")


class IsReadOnlyPlanOperationBench:
    """Benchmark is_read_only_plan_operation utility."""

    timeout = 60

    def time_check_strategize(self) -> None:
        """Benchmark checking strategize operation."""
        is_read_only_plan_operation({"plan_phase": "strategize"})

    def time_check_plan(self) -> None:
        """Benchmark checking plan operation."""
        is_read_only_plan_operation({"plan_phase": "plan"})

    def time_check_validate(self) -> None:
        """Benchmark checking validate operation."""
        is_read_only_plan_operation({"plan_phase": "validate"})

    def time_check_review(self) -> None:
        """Benchmark checking review operation."""
        is_read_only_plan_operation({"plan_phase": "review"})

    def time_check_preview(self) -> None:
        """Benchmark checking preview operation."""
        is_read_only_plan_operation({"plan_phase": "preview"})

    def time_check_check(self) -> None:
        """Benchmark checking check operation."""
        is_read_only_plan_operation({"plan_phase": "check"})

    def time_check_execute(self) -> None:
        """Benchmark checking execute operation (not read-only)."""
        is_read_only_plan_operation({"plan_phase": "execute"})

    def time_check_read_only_flag(self) -> None:
        """Benchmark checking read_only flag."""
        is_read_only_plan_operation({"read_only": True})

    def time_check_unknown_operation(self) -> None:
        """Benchmark checking unknown operation."""
        is_read_only_plan_operation({"plan_phase": "unknown_op"})

    def time_check_empty_kwargs(self) -> None:
        """Benchmark checking empty kwargs."""
        is_read_only_plan_operation({})


class RetryServiceOperationStrategyBench:
    """Benchmark different retry strategies in service operations."""

    timeout = 60

    def time_exponential_strategy(self) -> None:
        """Benchmark exponential strategy."""

        @retry_service_operation(
            service_name="test_service",
            operation_name="test_op",
            max_attempts=3,
            backoff_strategy="exponential",
        )
        def dummy() -> str:
            return "success"

        dummy()

    def time_linear_strategy(self) -> None:
        """Benchmark linear strategy."""

        @retry_service_operation(
            service_name="test_service",
            operation_name="test_op",
            max_attempts=3,
            backoff_strategy="linear",
        )
        def dummy() -> str:
            return "success"

        dummy()

    def time_fixed_strategy(self) -> None:
        """Benchmark fixed strategy."""

        @retry_service_operation(
            service_name="test_service",
            operation_name="test_op",
            max_attempts=3,
            backoff_strategy="fixed",
        )
        def dummy() -> str:
            return "success"

        dummy()

    def time_jitter_strategy(self) -> None:
        """Benchmark jitter strategy."""

        @retry_service_operation(
            service_name="test_service",
            operation_name="test_op",
            max_attempts=3,
            backoff_strategy="jitter",
        )
        def dummy() -> str:
            return "success"

        dummy()
