import pytest

from workflow_engine import ValidationContext, WorkflowEngine
from workflow_engine.nodes import ConstantStringNode


@pytest.fixture
def engine() -> WorkflowEngine:
    return WorkflowEngine()


@pytest.fixture
def node(engine: WorkflowEngine) -> ConstantStringNode:
    return engine.create_node(
        ConstantStringNode, id="test_node", params=dict(value="test")
    )


@pytest.mark.unit
def test_constant_string_node_type_info():
    """Test ConstantStringNode TYPE_INFO metadata."""
    assert ConstantStringNode.TYPE_INFO.model_dump(mode="json") == {
        "description": "A node that outputs a constant string value.",
        "display_name": "Constant String",
        "max_retries": None,
        "parameter_schema": {  # generated by Pydantic, we have little control over this
            "$defs": {
                "StringValue": {
                    "type": "string",
                    "title": "StringValue",
                },
            },
            "additionalProperties": False,
            "properties": {
                "value": {
                    "$ref": "#/$defs/StringValue",
                    "title": "Value",
                    "description": "The constant string value.",
                },
            },
            "required": ["value"],
            "title": "ConstantString",
            "type": "object",
        },
        "version": "0.4.0",
    }


@pytest.mark.unit
async def test_constant_string_node_output_schema_has_field_title_and_description(
    node: ConstantStringNode,
):
    """Field titles and descriptions should appear in the output schema."""
    context = ValidationContext()
    output_type = await node.output_type(context)
    output_schema = output_type.model_json_schema()
    value_prop = output_schema["properties"]["value"]
    assert value_prop["title"] == "Value"
    assert value_prop["description"] == "The constant string value."


@pytest.mark.unit
async def test_constant_string_node_input_schema(node: ConstantStringNode):
    context = ValidationContext()
    input_type = await node.input_type(context)
    input_schema = input_type.model_json_schema()
    assert input_schema == {
        "additionalProperties": False,
        "description": "A Data and Params class that is explicitly not allowed to have any\nparameters.",
        "properties": {},
        "title": "Empty",
        "type": "object",
    }


@pytest.mark.unit
async def test_constant_string_node_output_schema(node: ConstantStringNode):
    context = ValidationContext()
    output_type = await node.output_type(context)
    output_schema = output_type.model_json_schema()
    assert output_schema == {
        "$defs": {
            "StringValue": {
                "type": "string",
                "title": "StringValue",
            },
        },
        "additionalProperties": False,
        "properties": {
            "value": {
                "$ref": "#/$defs/StringValue",
                "title": "Value",
                "description": "The constant string value.",
            },
        },
        "required": ["value"],
        "title": "ConstantString",
        "type": "object",
    }
