"""Step definitions for ServiceRetryWiring settings override tests."""

from __future__ import annotations

import asyncio
from typing import Any

from behave import given, then, when

# ---------------------------------------------------------------------------
# Settings individual override scenarios
# ---------------------------------------------------------------------------


@given("I have Settings with non-default retry_max_attempts {value:d}")
def step_settings_max_attempts(context: Any, value: int) -> None:
    import os

    from cleveragents.config.settings import Settings

    os.environ["CLEVERAGENTS_RETRY_MAX_ATTEMPTS"] = str(value)
    try:
        context.settings = Settings(
            database_url="sqlite:///test_retry.db",
            mock_providers=True,
            env="test",
        )
    finally:
        os.environ.pop("CLEVERAGENTS_RETRY_MAX_ATTEMPTS", None)


@when("I create a ServiceRetryWiring from those max-attempts Settings")
def step_create_wiring_max_attempts(context: Any) -> None:
    from cleveragents.application.services.service_retry_wiring import (
        ServiceRetryWiring,
    )

    context.wiring = ServiceRetryWiring(context.settings)


@given("I have Settings with non-default circuit_breaker_failure_threshold {value:d}")
def step_settings_cb_threshold(context: Any, value: int) -> None:
    import os

    from cleveragents.config.settings import Settings

    os.environ["CLEVERAGENTS_CB_FAILURE_THRESHOLD"] = str(value)
    try:
        context.settings = Settings(
            database_url="sqlite:///test_retry.db",
            mock_providers=True,
            env="test",
        )
    finally:
        os.environ.pop("CLEVERAGENTS_CB_FAILURE_THRESHOLD", None)


@when("I create a ServiceRetryWiring from those cb-threshold Settings")
def step_create_wiring_cb_threshold(context: Any) -> None:
    from cleveragents.application.services.service_retry_wiring import (
        ServiceRetryWiring,
    )

    context.wiring = ServiceRetryWiring(context.settings)


@then("the plan_service circuit breaker should have failure_threshold {value:d}")
def step_check_cb_threshold_override(context: Any, value: int) -> None:
    cb = context.wiring.get_circuit_breaker("plan_service")
    assert cb is not None
    assert cb.failure_threshold == value


@when('I check is_circuit_open for "{name}"')
def step_check_is_circuit_open_unknown(context: Any, name: str) -> None:
    context.unknown_circuit_open = context.wiring.is_circuit_open(name)


@then("the circuit should report not open")
def step_verify_circuit_not_open(context: Any) -> None:
    assert context.unknown_circuit_open is False


@when("I async_execute the function with circuit breaker enabled")
def step_async_execute_with_cb(context: Any) -> None:
    loop = asyncio.new_event_loop()
    try:
        context.async_result = loop.run_until_complete(
            context.wiring.async_execute(
                service_name="plan_service",
                operation_name="test_async_cb_retry",
                func=context.async_test_func,
                idempotent=True,
            )
        )
        context.async_exec_error = None
    except Exception as exc:
        context.async_exec_error = exc
        context.async_result = None
    finally:
        loop.close()


@given("I have Settings with non-default retry_base_delay {value:g}")
def step_settings_base_delay(context: Any, value: float) -> None:
    import os

    from cleveragents.config.settings import Settings

    os.environ["CLEVERAGENTS_RETRY_BASE_DELAY"] = str(value)
    try:
        context.settings = Settings(
            database_url="sqlite:///test_retry.db",
            mock_providers=True,
            env="test",
        )
    finally:
        os.environ.pop("CLEVERAGENTS_RETRY_BASE_DELAY", None)


@when("I create a ServiceRetryWiring from those base-delay Settings")
def step_create_wiring_base_delay(context: Any) -> None:
    from cleveragents.application.services.service_retry_wiring import (
        ServiceRetryWiring,
    )

    context.wiring = ServiceRetryWiring(context.settings)


@then("the plan_service policy should have base_delay {value:g}")
def step_check_base_delay_override(context: Any, value: float) -> None:
    policy = context.wiring.get_policy("plan_service")
    assert policy.retry.base_delay == value


@given("I have Settings with non-default circuit_breaker_recovery_timeout {value:g}")
def step_settings_cb_recovery_timeout(context: Any, value: float) -> None:
    import os

    from cleveragents.config.settings import Settings

    os.environ["CLEVERAGENTS_CB_RECOVERY_TIMEOUT"] = str(value)
    try:
        context.settings = Settings(
            database_url="sqlite:///test_retry.db",
            mock_providers=True,
            env="test",
        )
    finally:
        os.environ.pop("CLEVERAGENTS_CB_RECOVERY_TIMEOUT", None)


@when("I create a ServiceRetryWiring from those recovery-timeout Settings")
def step_create_wiring_recovery_timeout(context: Any) -> None:
    from cleveragents.application.services.service_retry_wiring import (
        ServiceRetryWiring,
    )

    context.wiring = ServiceRetryWiring(context.settings)


@then("the plan_service circuit breaker should have recovery_timeout {value:g}")
def step_check_recovery_timeout_override(context: Any, value: float) -> None:
    cb = context.wiring.get_circuit_breaker("plan_service")
    assert cb is not None
    assert cb.recovery_timeout == value


@given("I have Settings with non-default circuit_breaker_cooldown {value:g}")
def step_settings_cb_cooldown(context: Any, value: float) -> None:
    import os

    from cleveragents.config.settings import Settings

    os.environ["CLEVERAGENTS_CB_COOLDOWN"] = str(value)
    try:
        context.settings = Settings(
            database_url="sqlite:///test_retry.db",
            mock_providers=True,
            env="test",
        )
    finally:
        os.environ.pop("CLEVERAGENTS_CB_COOLDOWN", None)


@when("I create a ServiceRetryWiring from those cooldown Settings")
def step_create_wiring_cooldown(context: Any) -> None:
    from cleveragents.application.services.service_retry_wiring import (
        ServiceRetryWiring,
    )

    context.wiring = ServiceRetryWiring(context.settings)


@then("the plan_service circuit breaker should have cooldown_seconds {value:g}")
def step_check_cooldown_override(context: Any, value: float) -> None:
    cb = context.wiring.get_circuit_breaker("plan_service")
    assert cb is not None
    assert cb.cooldown_seconds == value


@given("I have Settings with non-default retry_max_delay {value:g}")
def step_settings_max_delay(context: Any, value: float) -> None:
    import os

    from cleveragents.config.settings import Settings

    os.environ["CLEVERAGENTS_RETRY_MAX_DELAY"] = str(value)
    try:
        context.settings = Settings(
            database_url="sqlite:///test_retry.db",
            mock_providers=True,
            env="test",
        )
    finally:
        os.environ.pop("CLEVERAGENTS_RETRY_MAX_DELAY", None)


@when("I create a ServiceRetryWiring from those max-delay Settings")
def step_create_wiring_max_delay(context: Any) -> None:
    from cleveragents.application.services.service_retry_wiring import (
        ServiceRetryWiring,
    )

    context.wiring = ServiceRetryWiring(context.settings)


@then("the plan_service policy should have max_delay {value:g}")
def step_check_max_delay_override(context: Any, value: float) -> None:
    policy = context.wiring.get_policy("plan_service")
    assert policy.retry.max_delay == value


@given("I have Settings with non-default retry_jitter {value}")
def step_settings_jitter(context: Any, value: str) -> None:
    import os

    from cleveragents.config.settings import Settings

    os.environ["CLEVERAGENTS_RETRY_JITTER"] = value
    try:
        context.settings = Settings(
            database_url="sqlite:///test_retry.db",
            mock_providers=True,
            env="test",
        )
    finally:
        os.environ.pop("CLEVERAGENTS_RETRY_JITTER", None)


@when("I create a ServiceRetryWiring from those jitter Settings")
def step_create_wiring_jitter(context: Any) -> None:
    from cleveragents.application.services.service_retry_wiring import (
        ServiceRetryWiring,
    )

    context.wiring = ServiceRetryWiring(context.settings)


@then("the plan_service policy should have jitter {value}")
def step_check_jitter_override(context: Any, value: str) -> None:
    policy = context.wiring.get_policy("plan_service")
    expected = value == "True"
    assert policy.retry.jitter == expected
