"""Step definitions for OrgUserConfig coverage tests."""

import json
from datetime import UTC, datetime

from behave import then, when
from pydantic import ValidationError


@when("I import OrgUserConfig from orguserconfig")
def step_import_org_user_config(context):
    """Import OrgUserConfig class."""
    from cleveragents.domain.models.orguserconfig.org_user_config import (
        OrgUserConfig,
    )

    context.org_user_config_class = OrgUserConfig


@then("the OrgUserConfig class should be available")
def step_verify_org_user_config_available(context):
    """Verify OrgUserConfig class is available."""
    assert context.org_user_config_class is not None
    assert context.org_user_config_class.__name__ == "OrgUserConfig"


@then("I can create an OrgUserConfig with all required fields")
def step_create_full_org_user_config(context):
    """Create an OrgUserConfig with all fields."""
    OrgUserConfig = context.org_user_config_class

    # Create with all required fields
    config = OrgUserConfig(
        prompted_claude_max=True,
        use_claude_subscription=True,
        claude_subscription_cooldown_started_at=datetime.now(UTC),
    )

    assert config.prompted_claude_max is True
    assert config.use_claude_subscription is True
    assert isinstance(config.claude_subscription_cooldown_started_at, datetime)


@when("I create an OrgUserConfig with prompted_claude_max set to True")
def step_create_with_prompted_claude_max(context):
    """Create OrgUserConfig with prompted_claude_max field."""
    from cleveragents.domain.models.orguserconfig.org_user_config import (
        OrgUserConfig,
    )

    context.model_instance = OrgUserConfig(
        prompted_claude_max=True,
        use_claude_subscription=False,
        claude_subscription_cooldown_started_at=datetime.now(),
    )


@then("the OrgUserConfig should have prompted_claude_max as True")
def step_verify_prompted_claude_max(context):
    """Verify prompted_claude_max field value."""
    assert context.model_instance.prompted_claude_max is True


@then('the field should be accessible via the alias "promptedClaudeMax"')
def step_verify_prompted_claude_max_alias(context):
    """Verify the field can be accessed via its alias."""
    # Serialize to dict with aliases
    data = context.model_instance.model_dump(by_alias=True)
    assert "promptedClaudeMax" in data
    assert data["promptedClaudeMax"] is True


@when("I create an OrgUserConfig with use_claude_subscription set to False")
def step_create_with_use_claude_subscription(context):
    """Create OrgUserConfig with use_claude_subscription field."""
    from cleveragents.domain.models.orguserconfig.org_user_config import (
        OrgUserConfig,
    )

    context.model_instance = OrgUserConfig(
        prompted_claude_max=False,
        use_claude_subscription=False,
        claude_subscription_cooldown_started_at=datetime.now(),
    )


@then("the OrgUserConfig should have use_claude_subscription as False")
def step_verify_use_claude_subscription(context):
    """Verify use_claude_subscription field value."""
    assert context.model_instance.use_claude_subscription is False


@then('the field should be accessible via the alias "useClaudeSubscription"')
def step_verify_use_claude_subscription_alias(context):
    """Verify the field can be accessed via its alias."""
    data = context.model_instance.model_dump(by_alias=True)
    assert "useClaudeSubscription" in data
    assert data["useClaudeSubscription"] is False


@when("I create an OrgUserConfig with a specific cooldown timestamp")
def step_create_with_cooldown_timestamp(context):
    """Create OrgUserConfig with specific timestamp."""
    from cleveragents.domain.models.orguserconfig.org_user_config import (
        OrgUserConfig,
    )

    context.timestamp = datetime(2024, 1, 15, 10, 30, 0, tzinfo=UTC)
    context.model_instance = OrgUserConfig(
        prompted_claude_max=True,
        use_claude_subscription=True,
        claude_subscription_cooldown_started_at=context.timestamp,
    )


@then("the OrgUserConfig should have the correct timestamp")
def step_verify_timestamp(context):
    """Verify timestamp field value."""
    assert (
        context.model_instance.claude_subscription_cooldown_started_at
        == context.timestamp
    )


@then(
    'the field should be accessible via the alias "claudeSubscriptionCooldownStartedAt"'
)
def step_verify_cooldown_alias(context):
    """Verify the cooldown field can be accessed via its alias."""
    data = context.model_instance.model_dump(by_alias=True)
    assert "claudeSubscriptionCooldownStartedAt" in data


@when("I create an OrgUserConfig with fields containing whitespace")
def step_create_with_whitespace(context):
    """Create OrgUserConfig to test whitespace stripping."""
    from cleveragents.domain.models.orguserconfig.org_user_config import (
        OrgUserConfig,
    )

    # Note: OrgUserConfig doesn't have string fields, but we test the config is set
    context.model_instance = OrgUserConfig(
        prompted_claude_max=True,
        use_claude_subscription=False,
        claude_subscription_cooldown_started_at=datetime.now(),
    )


@then("OrgUserConfig string fields should have whitespace stripped")
def step_verify_orguserconfig_whitespace_stripped(context):
    """Verify whitespace stripping config is active for OrgUserConfig."""
    # Check that the model_config has str_strip_whitespace enabled
    assert context.model_instance.model_config.get("str_strip_whitespace") is True


@when("I create an OrgUserConfig instance")
def step_create_instance(context):
    """Create a basic OrgUserConfig instance."""
    from cleveragents.domain.models.orguserconfig.org_user_config import (
        OrgUserConfig,
    )

    context.model_instance = OrgUserConfig(
        prompted_claude_max=False,
        use_claude_subscription=True,
        claude_subscription_cooldown_started_at=datetime.now(),
    )


@when("I update its fields with new values for OrgUserConfig")
def step_update_orguserconfig_fields(context):
    """Update fields on the OrgUserConfig instance."""
    # Update fields to trigger validation
    context.model_instance.prompted_claude_max = True
    context.model_instance.use_claude_subscription = False
    context.model_instance.claude_subscription_cooldown_started_at = datetime(
        2024, 12, 1
    )


@then("the OrgUserConfig assignment validation should be triggered")
def step_verify_orguserconfig_assignment_validation(context):
    """Verify assignment validation is active for OrgUserConfig."""
    assert context.model_instance.model_config.get("validate_assignment") is True


@then("the OrgUserConfig values should be properly validated")
def step_verify_orguserconfig_values_validated(context):
    """Verify the updated values are correct for OrgUserConfig."""
    assert context.model_instance.prompted_claude_max is True
    assert context.model_instance.use_claude_subscription is False
    assert context.model_instance.claude_subscription_cooldown_started_at == datetime(
        2024, 12, 1
    )


@when("I create an OrgUserConfig using camelCase field aliases")
def step_create_with_camel_case_aliases(context):
    """Create OrgUserConfig using camelCase aliases."""
    from cleveragents.domain.models.orguserconfig.org_user_config import (
        OrgUserConfig,
    )

    # Create using aliases
    context.model_instance = OrgUserConfig(
        **{
            "promptedClaudeMax": True,
            "useClaudeSubscription": False,
            "claudeSubscriptionCooldownStartedAt": datetime.now(),
        }
    )


@then("the OrgUserConfig fields should be populated correctly by name")
def step_verify_orguserconfig_populate_by_name(context):
    """Verify OrgUserConfig fields are populated correctly."""
    assert context.model_instance.prompted_claude_max is True
    assert context.model_instance.use_claude_subscription is False
    assert context.model_instance.claude_subscription_cooldown_started_at is not None


@then("both snake_case and camelCase access should work")
def step_verify_both_access_methods(context):
    """Verify both naming conventions work."""
    # Snake case access
    assert hasattr(context.model_instance, "prompted_claude_max")
    assert hasattr(context.model_instance, "use_claude_subscription")

    # CamelCase through serialization
    data = context.model_instance.model_dump(by_alias=True)
    assert "promptedClaudeMax" in data
    assert "useClaudeSubscription" in data


@when("I create an OrgUserConfig from a dictionary with camelCase keys")
def step_create_from_dict_with_aliases(context):
    """Create OrgUserConfig from dictionary with aliases."""
    from cleveragents.domain.models.orguserconfig.org_user_config import (
        OrgUserConfig,
    )

    context.input_data = {
        "promptedClaudeMax": False,
        "useClaudeSubscription": True,
        "claudeSubscriptionCooldownStartedAt": "2024-01-15T10:30:00Z",
    }

    context.model_instance = OrgUserConfig(**context.input_data)


@then("the model should correctly map aliased fields")
def step_verify_aliased_field_mapping(context):
    """Verify aliased fields are correctly mapped."""
    assert context.model_instance.prompted_claude_max is False
    assert context.model_instance.use_claude_subscription is True


@then("all fields should be accessible with snake_case names")
def step_verify_snake_case_access(context):
    """Verify all fields accessible with snake_case."""
    assert context.model_instance.prompted_claude_max is False
    assert context.model_instance.use_claude_subscription is True
    assert isinstance(
        context.model_instance.claude_subscription_cooldown_started_at, datetime
    )


@when("I create an OrgUserConfig and serialize it")
def step_create_and_serialize(context):
    """Create and serialize an OrgUserConfig."""
    from cleveragents.domain.models.orguserconfig.org_user_config import (
        OrgUserConfig,
    )

    context.model_instance = OrgUserConfig(
        prompted_claude_max=True,
        use_claude_subscription=False,
        claude_subscription_cooldown_started_at=datetime(2024, 1, 15, 10, 30, 0),
    )

    context.serialized = context.model_instance.model_dump(by_alias=True)


@then("the serialized output should use the defined aliases")
def step_verify_serialized_aliases(context):
    """Verify serialized output uses aliases."""
    assert "promptedClaudeMax" in context.serialized
    assert "useClaudeSubscription" in context.serialized
    assert "claudeSubscriptionCooldownStartedAt" in context.serialized
    assert context.serialized["promptedClaudeMax"] is True
    assert context.serialized["useClaudeSubscription"] is False


@then("the model should be deserializable from the serialized form")
def step_verify_deserializable(context):
    """Verify model can be deserialized."""
    from cleveragents.domain.models.orguserconfig.org_user_config import (
        OrgUserConfig,
    )

    # Recreate from serialized data
    new_instance = OrgUserConfig(**context.serialized)
    assert new_instance.prompted_claude_max is True
    assert new_instance.use_claude_subscription is False


@when("I try to create an OrgUserConfig with an invalid datetime string")
def step_create_with_invalid_datetime(context):
    """Try to create OrgUserConfig with invalid datetime."""
    from cleveragents.domain.models.orguserconfig.org_user_config import (
        OrgUserConfig,
    )

    try:
        OrgUserConfig(
            prompted_claude_max=True,
            use_claude_subscription=False,
            claude_subscription_cooldown_started_at="not-a-datetime",
        )
        context.validation_error = None
    except ValidationError as e:
        context.validation_error = e


@then("an OrgUserConfig validation error should be raised")
def step_verify_orguserconfig_validation_error(context):
    """Verify a validation error was raised for OrgUserConfig."""
    assert context.validation_error is not None
    assert isinstance(context.validation_error, ValidationError)


@then("the error should indicate the datetime field")
def step_verify_datetime_error(context):
    """Verify error mentions datetime field."""
    errors = context.validation_error.errors()
    field_names = [err["loc"][0] for err in errors]
    assert "claude_subscription_cooldown_started_at" in field_names


@when("I try to create an OrgUserConfig without required fields")
def step_create_without_required_fields(context):
    """Try to create OrgUserConfig without required fields."""
    from cleveragents.domain.models.orguserconfig.org_user_config import (
        OrgUserConfig,
    )

    try:
        OrgUserConfig()
        context.validation_error = None
    except ValidationError as e:
        context.validation_error = e


@then("the error should list all missing required fields")
def step_verify_missing_fields_error(context):
    """Verify error lists missing required fields."""
    errors = context.validation_error.errors()
    # Check there are errors for missing fields
    assert len(errors) >= 3  # We have 3 required fields


@when("I inspect the OrgUserConfig model configuration")
def step_inspect_model_config(context):
    """Inspect the model configuration."""
    from cleveragents.domain.models.orguserconfig.org_user_config import (
        OrgUserConfig,
    )

    context.model_config = OrgUserConfig.model_config


@then("OrgUserConfig str_strip_whitespace should be True")
def step_verify_orguserconfig_strip_whitespace_config(context):
    """Verify OrgUserConfig str_strip_whitespace config."""
    assert context.model_config.get("str_strip_whitespace") is True


@then("OrgUserConfig validate_assignment should be True")
def step_verify_orguserconfig_validate_assignment_config(context):
    """Verify OrgUserConfig validate_assignment config."""
    assert context.model_config.get("validate_assignment") is True


@then("OrgUserConfig arbitrary_types_allowed should be False")
def step_verify_orguserconfig_arbitrary_types_config(context):
    """Verify OrgUserConfig arbitrary_types_allowed config."""
    assert context.model_config.get("arbitrary_types_allowed") is False


@then("OrgUserConfig populate_by_name should be True")
def step_verify_orguserconfig_populate_by_name_config(context):
    """Verify OrgUserConfig populate_by_name config."""
    assert context.model_config.get("populate_by_name") is True


@then("OrgUserConfig use_enum_values should be True")
def step_verify_orguserconfig_use_enum_values_config(context):
    """Verify OrgUserConfig use_enum_values config."""
    assert context.model_config.get("use_enum_values") is True


@when("I create an OrgUserConfig with a timezone-aware datetime")
def step_create_with_timezone_aware_datetime(context):
    """Create OrgUserConfig with timezone-aware datetime."""
    from cleveragents.domain.models.orguserconfig.org_user_config import (
        OrgUserConfig,
    )

    context.tz_datetime = datetime(2024, 6, 15, 14, 30, 0, tzinfo=UTC)
    context.model_instance = OrgUserConfig(
        prompted_claude_max=True,
        use_claude_subscription=True,
        claude_subscription_cooldown_started_at=context.tz_datetime,
    )


@then("the model should handle the timezone information correctly")
def step_verify_timezone_handling(context):
    """Verify timezone information is preserved."""
    stored_dt = context.model_instance.claude_subscription_cooldown_started_at
    assert stored_dt == context.tz_datetime
    assert stored_dt.tzinfo is not None


@then("the datetime should be properly stored")
def step_verify_datetime_stored(context):
    """Verify datetime is properly stored."""
    assert (
        context.model_instance.claude_subscription_cooldown_started_at
        == context.tz_datetime
    )


@when("I create an OrgUserConfig and copy it with updates")
def step_create_and_copy_with_updates(context):
    """Create OrgUserConfig and copy with updates."""
    from cleveragents.domain.models.orguserconfig.org_user_config import (
        OrgUserConfig,
    )

    context.original = OrgUserConfig(
        prompted_claude_max=False,
        use_claude_subscription=True,
        claude_subscription_cooldown_started_at=datetime(2024, 1, 1),
    )

    # Copy with updates
    context.copy = context.original.model_copy(
        update={"prompted_claude_max": True, "use_claude_subscription": False}
    )


@then("the OrgUserConfig copy should have the updated values")
def step_verify_orguserconfig_copy_updated(context):
    """Verify the OrgUserConfig copy has updated values."""
    assert context.copy.prompted_claude_max is True
    assert context.copy.use_claude_subscription is False


@then("the OrgUserConfig original should remain unchanged")
def step_verify_orguserconfig_original_unchanged(context):
    """Verify OrgUserConfig original remains unchanged."""
    assert context.original.prompted_claude_max is False
    assert context.original.use_claude_subscription is True


@when("I create an OrgUserConfig and call model_dump with by_alias=True")
def step_model_dump_with_alias_true(context):
    """Call model_dump with by_alias=True."""
    from cleveragents.domain.models.orguserconfig.org_user_config import (
        OrgUserConfig,
    )

    context.model_instance = OrgUserConfig(
        prompted_claude_max=True,
        use_claude_subscription=False,
        claude_subscription_cooldown_started_at=datetime(2024, 3, 15),
    )

    context.dump_with_alias = context.model_instance.model_dump(by_alias=True)


@then("the output should use camelCase aliases")
def step_verify_camel_case_output(context):
    """Verify output uses camelCase aliases."""
    assert "promptedClaudeMax" in context.dump_with_alias
    assert "useClaudeSubscription" in context.dump_with_alias
    assert "claudeSubscriptionCooldownStartedAt" in context.dump_with_alias

    # Verify snake_case is not present
    assert "prompted_claude_max" not in context.dump_with_alias
    assert "use_claude_subscription" not in context.dump_with_alias


@when("I call model_dump with by_alias=False")
def step_model_dump_with_alias_false(context):
    """Call model_dump with by_alias=False."""
    context.dump_without_alias = context.model_instance.model_dump(by_alias=False)


@then("the output should use snake_case field names")
def step_verify_snake_case_output(context):
    """Verify output uses snake_case field names."""
    assert "prompted_claude_max" in context.dump_without_alias
    assert "use_claude_subscription" in context.dump_without_alias
    assert "claude_subscription_cooldown_started_at" in context.dump_without_alias

    # Verify camelCase is not present
    assert "promptedClaudeMax" not in context.dump_without_alias
    assert "useClaudeSubscription" not in context.dump_without_alias


@when("I create an OrgUserConfig and call model_dump_json")
def step_model_dump_json(context):
    """Call model_dump_json on OrgUserConfig."""
    from cleveragents.domain.models.orguserconfig.org_user_config import (
        OrgUserConfig,
    )

    context.model_instance = OrgUserConfig(
        prompted_claude_max=False,
        use_claude_subscription=True,
        claude_subscription_cooldown_started_at=datetime(2024, 5, 20, 8, 30, 0),
    )

    context.json_output = context.model_instance.model_dump_json()


@then("the JSON output should be valid")
def step_verify_valid_json(context):
    """Verify JSON output is valid."""
    # Should be able to parse the JSON
    data = json.loads(context.json_output)
    assert data is not None


@then("it should use the configured aliases by default")
def step_verify_json_uses_aliases(context):
    """Verify JSON uses aliases by default."""
    data = json.loads(context.json_output)
    # model_dump_json by default uses by_alias=False in Pydantic v2
    # Check that field names are present (either snake_case or camelCase)
    assert "prompted_claude_max" in data or "promptedClaudeMax" in data
    assert "use_claude_subscription" in data or "useClaudeSubscription" in data
    assert (
        "claude_subscription_cooldown_started_at" in data
        or "claudeSubscriptionCooldownStartedAt" in data
    )


@when("I try to create an OrgUserConfig with wrong field types")
def step_create_with_wrong_types(context):
    """Try to create OrgUserConfig with wrong field types."""
    from cleveragents.domain.models.orguserconfig.org_user_config import (
        OrgUserConfig,
    )

    try:
        OrgUserConfig(
            prompted_claude_max="not_a_bool",  # Should be bool
            use_claude_subscription=123,  # Should be bool
            claude_subscription_cooldown_started_at=456,  # Should be datetime
        )
        context.validation_error = None
    except ValidationError as e:
        context.validation_error = e


@then("validation errors should be raised for type mismatches")
def step_verify_type_mismatch_errors(context):
    """Verify validation errors for type mismatches."""
    assert context.validation_error is not None
    errors = context.validation_error.errors()
    # Pydantic may coerce some values, so check at least one error
    assert len(errors) >= 1


@then("the OrgUserConfig errors should clearly indicate the expected types")
def step_verify_orguserconfig_error_types(context):
    """Verify OrgUserConfig errors indicate expected types."""
    errors = context.validation_error.errors()
    # Check that there are errors for wrong types
    assert len(errors) > 0


@when("I import the orguserconfig __init__ module")
def step_import_init_module(context):
    """Import the orguserconfig __init__ module."""
    import cleveragents.domain.models.orguserconfig

    context.init_module = cleveragents.domain.models.orguserconfig


@then("the module should be loaded successfully")
def step_verify_module_loaded(context):
    """Verify the __init__ module is loaded."""
    assert context.init_module is not None


@then("the OrgUserConfig class should be importable from it")
def step_verify_class_importable_from_init(context):
    """Verify OrgUserConfig can be imported from __init__."""
    # Import the __init__ module to ensure it's covered
    from cleveragents.domain.models.orguserconfig import OrgUserConfig

    assert OrgUserConfig is not None
    assert OrgUserConfig.__name__ == "OrgUserConfig"
