from core.session import Session


def _session() -> Session:
    # Skip heavyweight runtime initialization (VAD model, services, transport).
    return Session.__new__(Session)


def test_apply_dynamic_variables_substitutes_prompt_and_greeting():
    session = _session()
    metadata = {
        "systemPrompt": "Hello {{customer_name}}, plan={{plan_tier}}.",
        "greeting": "Hi {{customer_name}}",
    }
    client_metadata = {
        "dynamicVariables": {
            "customer_name": "Alice",
            "plan_tier": "Pro",
        }
    }

    resolved, error = session._apply_dynamic_variables(metadata, client_metadata)

    assert error is None
    assert resolved["systemPrompt"] == "Hello Alice, plan=Pro."
    assert resolved["greeting"] == "Hi Alice"


def test_apply_dynamic_variables_missing_value_rejects_session_start():
    session = _session()
    metadata = {
        "systemPrompt": "Hello {{customer_name}}",
        "greeting": "Plan {{plan_tier}}",
    }
    client_metadata = {
        "dynamicVariables": {
            "customer_name": "Alice",
        }
    }

    _, error = session._apply_dynamic_variables(metadata, client_metadata)

    assert error is not None
    assert error["code"] == "protocol.dynamic_variables_missing"
    assert "plan_tier" in error["message"]


def test_apply_dynamic_variables_requires_string_values():
    session = _session()
    metadata = {
        "systemPrompt": "Hello {{customer_name}}",
        "greeting": "Hi",
    }
    client_metadata = {
        "dynamicVariables": {
            "customer_name": 123,
        }
    }

    _, error = session._apply_dynamic_variables(metadata, client_metadata)

    assert error is not None
    assert error["code"] == "protocol.dynamic_variables_invalid"
    assert "must be a string" in error["message"]


def test_apply_dynamic_variables_missing_object_rejects_when_template_uses_placeholders():
    session = _session()
    metadata = {
        "systemPrompt": "Hello {{customer_name}}",
        "greeting": "Hi",
    }

    _, error = session._apply_dynamic_variables(metadata, {})

    assert error is not None
    assert error["code"] == "protocol.dynamic_variables_missing"
    assert "customer_name" in error["message"]


def test_apply_dynamic_variables_no_placeholder_keeps_metadata():
    session = _session()
    metadata = {
        "systemPrompt": "Hello there",
        "greeting": "Hi",
    }
    client_metadata = {
        "dynamicVariables": {
            "customer_name": "Alice",
        }
    }

    resolved, error = session._apply_dynamic_variables(metadata, client_metadata)

    assert error is None
    assert resolved == metadata


def test_apply_dynamic_variables_supports_system_time_variables_without_client_payload():
    session = _session()
    metadata = {
        "systemPrompt": "Now={{system__time}} utc={{system_utc}} tz={{system_timezone}}",
        "greeting": "Clock {{system__time}}",
    }

    resolved, error = session._apply_dynamic_variables(metadata, {})

    assert error is None
    assert "{{system__time}}" not in resolved["systemPrompt"]
    assert "{{system_utc}}" not in resolved["systemPrompt"]
    assert "{{system_timezone}}" not in resolved["systemPrompt"]
    assert "{{system__time}}" not in resolved["greeting"]


def test_apply_dynamic_variables_keeps_system_variables_reserved():
    session = _session()
    metadata = {
        "systemPrompt": "Clock={{system__time}} Name={{customer_name}}",
        "greeting": "Hi {{customer_name}}",
    }
    client_metadata = {
        "dynamicVariables": {
            "system__time": "manual_override",
            "customer_name": "Alice",
        }
    }

    resolved, error = session._apply_dynamic_variables(metadata, client_metadata)

    assert error is None
    assert "manual_override" not in resolved["systemPrompt"]
    assert "Alice" in resolved["systemPrompt"]
