"""
Tests for schema conversion: Ape → OpenAI.
"""

import pytest
from unittest.mock import Mock

from ape_openai.schema import (
    ape_task_to_openai_schema,
    map_ape_type_to_openai,
    openai_schema_to_ape_stub,
    APE_TO_OPENAI_TYPE_MAP
)
from ape_openai import ApeTask


def test_map_ape_type_to_openai():
    """Test type mapping from Ape to OpenAI."""
    assert map_ape_type_to_openai("String") == "string"
    assert map_ape_type_to_openai("Integer") == "integer"
    assert map_ape_type_to_openai("Float") == "number"
    assert map_ape_type_to_openai("Boolean") == "boolean"
    assert map_ape_type_to_openai("List") == "array"
    assert map_ape_type_to_openai("Dict") == "object"
    assert map_ape_type_to_openai("Unknown") == "string"  # Fallback


def test_ape_task_to_openai_schema_basic():
    """Test basic schema conversion."""
    task = ApeTask(
        name="add",
        inputs={"a": "int", "b": "int"},
        output="int",
        description="Add two numbers"
    )
    
    schema = ape_task_to_openai_schema(task)
    
    assert schema["type"] == "function"
    assert schema["function"]["name"] == "add"
    assert schema["function"]["description"] == "Add two numbers"
    
    params = schema["function"]["parameters"]
    assert params["type"] == "object"
    assert "a" in params["properties"]
    assert "b" in params["properties"]
    assert params["properties"]["a"]["type"] == "integer"
    assert params["properties"]["b"]["type"] == "integer"
    assert set(params["required"]) == {"a", "b"}


def test_ape_task_to_openai_schema_no_description():
    """Test schema conversion without description."""
    task = ApeTask(
        name="multiply",
        inputs={"x": "float", "y": "float"},
        output="float"
    )
    
    schema = ape_task_to_openai_schema(task)
    
    assert schema["function"]["description"] == "Deterministic Ape task: multiply"


def test_ape_task_to_openai_schema_various_types():
    """Test schema conversion with various types."""
    task = ApeTask(
        name="complex_task",
        inputs={
            "name": "String",
            "count": "Integer",
            "rate": "Float",
            "enabled": "Boolean",
            "items": "List"
        }
    )
    
    schema = ape_task_to_openai_schema(task)
    props = schema["function"]["parameters"]["properties"]
    
    assert props["name"]["type"] == "string"
    assert props["count"]["type"] == "integer"
    assert props["rate"]["type"] == "number"
    assert props["enabled"]["type"] == "boolean"
    assert props["items"]["type"] == "array"


def test_ape_task_to_openai_schema_with_return_type():
    """Test that return type is included in schema."""
    task = ApeTask(
        name="calculate",
        inputs={"x": "int"},
        output="float"
    )
    
    schema = ape_task_to_openai_schema(task)
    
    assert "returns" in schema["function"]
    assert schema["function"]["returns"]["type"] == "number"


def test_openai_schema_to_ape_stub():
    """Test reverse conversion: OpenAI schema → Ape stub."""
    schema = {
        "function": {
            "name": "calculate_tax",
            "parameters": {
                "properties": {
                    "amount": {"type": "number"},
                    "rate": {"type": "number"}
                }
            }
        }
    }
    
    ape_stub = openai_schema_to_ape_stub(schema)
    
    assert "task calculate_tax" in ape_stub
    assert "amount: Float" in ape_stub or "amount: Integer" in ape_stub
    assert "rate: Float" in ape_stub or "rate: Integer" in ape_stub
    assert "inputs:" in ape_stub
    assert "outputs:" in ape_stub
    assert "constraints:" in ape_stub
    assert "steps:" in ape_stub


def test_ape_task_empty_inputs():
    """Test schema conversion with no inputs."""
    task = ApeTask(
        name="get_timestamp",
        inputs={},
        output="String"
    )
    
    schema = ape_task_to_openai_schema(task)
    
    assert schema["function"]["parameters"]["properties"] == {}
    assert schema["function"]["parameters"]["required"] == []


def test_type_mapping_completeness():
    """Test that all defined types have mappings."""
    for ape_type in APE_TO_OPENAI_TYPE_MAP:
        openai_type = map_ape_type_to_openai(ape_type)
        assert openai_type in ["string", "integer", "number", "boolean", "array", "object"]
