"""Step definitions for Settings spec-required env var fields (issue #2866)."""

from __future__ import annotations

import os

from behave import given, then, when

from cleveragents.config.settings import Settings

_SPEC_FIELD_ENV_VARS = [
    "CLEVERAGENTS_SERVER_URL",
    "CLEVERAGENTS_SERVER_TOKEN",
    "CLEVERAGENTS_FORMAT",
    "CLEVERAGENTS_DEFAULT_ESTIMATION_ACTOR",
]


@given("no CleverAgents spec-field env vars are set")
def step_clear_spec_field_env_vars(context):
    """Remove all spec-field env vars so Settings starts from a clean slate."""
    for key in _SPEC_FIELD_ENV_VARS:
        os.environ.pop(key, None)
    if not hasattr(context, "env_vars_to_clean"):
        context.env_vars_to_clean = []
    context.env_vars_to_clean.extend(_SPEC_FIELD_ENV_VARS)


@when("I instantiate Settings for spec fields")
def step_instantiate_settings_for_spec_fields(context):
    """Create a fresh Settings instance (bypassing the singleton)."""
    Settings._instance = None
    context.settings = Settings()


@when("I inspect Settings.model_fields")
def step_inspect_model_fields(context):
    """Capture the model_fields mapping for assertion."""
    context.model_fields = Settings.model_fields


# ── server_url assertions ────────────────────────────────────────────────────


@then("settings.server_url should be None")
def step_server_url_is_none(context):
    assert context.settings.server_url is None, (
        f"Expected server_url to be None, got {context.settings.server_url!r}"
    )


@then('settings.server_url should be "{expected}"')
def step_server_url_equals(context, expected):
    assert context.settings.server_url == expected, (
        f"Expected server_url={expected!r}, got {context.settings.server_url!r}"
    )


# ── server_token assertions ──────────────────────────────────────────────────


@then("settings.server_token should be None")
def step_server_token_is_none(context):
    assert context.settings.server_token is None, (
        f"Expected server_token to be None, got {context.settings.server_token!r}"
    )


@then('settings.server_token should be "{expected}"')
def step_server_token_equals(context, expected):
    assert context.settings.server_token == expected, (
        f"Expected server_token={expected!r}, got {context.settings.server_token!r}"
    )


# ── format assertions ────────────────────────────────────────────────────────


@then("settings.format should be None")
def step_format_is_none(context):
    assert context.settings.format is None, (
        f"Expected format to be None, got {context.settings.format!r}"
    )


@then('settings.format should be "{expected}"')
def step_format_equals(context, expected):
    assert context.settings.format == expected, (
        f"Expected format={expected!r}, got {context.settings.format!r}"
    )


# ── default_estimation_actor assertions ──────────────────────────────────────


@then("settings.default_estimation_actor should be None")
def step_default_estimation_actor_is_none(context):
    assert context.settings.default_estimation_actor is None, (
        "Expected default_estimation_actor to be None, "
        f"got {context.settings.default_estimation_actor!r}"
    )


@then('settings.default_estimation_actor should be "{expected}"')
def step_default_estimation_actor_equals(context, expected):
    assert context.settings.default_estimation_actor == expected, (
        f"Expected default_estimation_actor={expected!r}, "
        f"got {context.settings.default_estimation_actor!r}"
    )


# ── model_fields presence assertions ─────────────────────────────────────────


@then('"{field_name}" should be present in model_fields')
def step_field_in_model_fields(context, field_name):
    assert field_name in context.model_fields, (
        f"Expected '{field_name}' to be in Settings.model_fields, "
        f"but only found: {sorted(context.model_fields.keys())}"
    )


# ── type annotation assertions ───────────────────────────────────────────────


@then("settings.server_url should be of type str or None")
def step_server_url_type(context):
    value = context.settings.server_url
    assert value is None or isinstance(value, str), (
        f"Expected server_url to be str | None, got {type(value)}"
    )


@then("settings.server_token should be of type str or None")
def step_server_token_type(context):
    value = context.settings.server_token
    assert value is None or isinstance(value, str), (
        f"Expected server_token to be str | None, got {type(value)}"
    )


@then("settings.format should be of type str or None")
def step_format_type(context):
    value = context.settings.format
    assert value is None or isinstance(value, str), (
        f"Expected format to be str | None, got {type(value)}"
    )


@then("settings.default_estimation_actor should be of type str or None")
def step_default_estimation_actor_type(context):
    value = context.settings.default_estimation_actor
    assert value is None or isinstance(value, str), (
        f"Expected default_estimation_actor to be str | None, got {type(value)}"
    )
