from __future__ import annotations

import os
from typing import Any

from behave import given, then, when

from cleveragents.config import settings as settings_module
from features.environment import LANGSMITH_ENV_VARS


def _ensure_env_tracking(context: Any) -> None:
    if not hasattr(context, "env_vars_to_clean"):
        context.env_vars_to_clean = []


@given("LangSmith environment is clean")
def step_clear_langsmith_env(context):
    _ensure_env_tracking(context)
    for key in LANGSMITH_ENV_VARS:
        os.environ.pop(key, None)
    context.env_vars_to_clean.clear()


@given('I set environment variable "{name}" to "{value}"')
def step_set_env_var(context, name: str, value: str):
    _ensure_env_tracking(context)
    os.environ[name] = value
    context.env_vars_to_clean.append(name)


@when("I load CleverAgents settings for LangSmith")
def step_load_settings(context):
    settings_module.Settings._instance = None
    context.langsmith_settings = settings_module.get_settings()


@when('I build a LangSmith config with run name "{run_name}"')
def step_build_langsmith_config(context, run_name: str):
    settings_obj = getattr(context, "langsmith_settings", None)
    assert settings_obj is not None, "LangSmith settings not loaded"
    context.langsmith_config = settings_obj.build_langsmith_config(
        tags=["context-analysis", "behave-test"],
        metadata={"scenario": "langsmith_config", "run_name": run_name},
        run_name=run_name,
    )


@then("LangSmith tracing should be disabled")
def step_assert_tracing_disabled(context):
    settings_obj = getattr(context, "langsmith_settings", None)
    assert settings_obj is not None, "LangSmith settings not loaded"
    assert not settings_obj.is_langsmith_enabled, "Tracing unexpectedly enabled"


@then("LangSmith tracing should be enabled")
def step_assert_tracing_enabled(context):
    settings_obj = getattr(context, "langsmith_settings", None)
    assert settings_obj is not None, "LangSmith settings not loaded"
    assert settings_obj.is_langsmith_enabled, "Tracing was not enabled"


@then('the LangSmith config should include tag "{tag}"')
def step_assert_config_tag(context, tag: str):
    config = getattr(context, "langsmith_config", None)
    assert config, "LangSmith config was not built"
    tags = config.get("tags", [])
    assert tag in tags, f"Expected tag '{tag}' in {tags}"


@then('the LangSmith config should include metadata key "{key}"')
def step_then_the_langsmith_config_should_include_metadata_key(context, key):
    config = getattr(context, "langsmith_config", None)
    assert config, "LangSmith config was not built"
    metadata = config.get("metadata", {})
    assert key in metadata, f"Expected metadata key '{key}' in {metadata}"


@then('the LangSmith config should include metadata value "{value}" for key "{key}"')
def step_assert_langsmith_metadata_value(context, value: str, key: str):
    config = getattr(context, "langsmith_config", None)
    assert config, "LangSmith config was not built"
    metadata = config.get("metadata", {})
    actual = metadata.get(key)
    assert actual == value, f"Expected metadata {key}={value}, received {actual}"


@then('the LangSmith validation errors should mention "{message}"')
def step_assert_langsmith_validation_errors(context, message: str):
    settings_obj = getattr(context, "langsmith_settings", None)
    assert settings_obj is not None, "LangSmith settings not loaded"
    errors = settings_obj.langsmith_validation_errors
    assert errors, "Expected validation errors but none recorded"
    assert any(message in err for err in errors), errors


@then('the environment variable "{name}" should equal "{value}"')
def step_assert_environment_variable(context, name: str, value: str):
    actual = os.getenv(name)
    assert actual == value, f"Expected {name}={value}, received {actual}"
