# Copyright (c) 2025 CoReason, Inc.
#
# This software is proprietary and dual-licensed.
# Licensed under the Prosperity Public License 3.0 (the "License").
# A copy of the license is available at https://prosperitylicense.com/versions/3.0.0
# For details, see the LICENSE file.
# Commercial use beyond a 30-day trial requires a separate license.
#
# Source Code: https://github.com/CoReason-AI/coreason-manifest

import pytest
from pydantic import ValidationError

from coreason_manifest.spec.v2.definitions import (
    AgentDefinition,
    InlineToolDefinition,
    ToolRequirement,
)


def test_remote_tool_compatibility() -> None:
    """Validate remote tool compatibility."""
    data = {
        "id": "agent-1",
        "name": "My Agent",
        "role": "Worker",
        "goal": "Work",
        "tools": [{"type": "remote", "uri": "mcp://foo"}],
    }
    agent = AgentDefinition.model_validate(data)
    assert len(agent.tools) == 1
    tool = agent.tools[0]
    assert isinstance(tool, ToolRequirement)
    assert tool.type == "remote"
    assert tool.uri == "mcp://foo"


def test_inline_tool_parsing() -> None:
    """Validate inline tool parsing."""
    data = {
        "id": "agent-2",
        "name": "My Agent",
        "role": "Worker",
        "goal": "Work",
        "tools": [
            {
                "type": "inline",
                "name": "calculator",
                "description": "Add numbers",
                "parameters": {"type": "object", "properties": {}},
            }
        ],
    }
    agent = AgentDefinition.model_validate(data)
    assert len(agent.tools) == 1
    tool = agent.tools[0]
    assert isinstance(tool, InlineToolDefinition)
    assert tool.type == "inline"
    assert tool.name == "calculator"
    assert tool.parameters == {"type": "object", "properties": {}}


def test_validation_error_invalid_schema() -> None:
    """Pass an inline tool with invalid parameters (not a schema object)."""
    data = {
        "id": "agent-3",
        "name": "My Agent",
        "role": "Worker",
        "goal": "Work",
        "tools": [
            {
                "type": "inline",
                "name": "bad_tool",
                "description": "Bad Schema",
                "parameters": {"type": "string"},  # Invalid, must be object
            }
        ],
    }
    with pytest.raises(ValidationError) as exc:
        AgentDefinition.model_validate(data)

    # Check that the error is related to validation
    assert "Tool parameters must be a JSON Schema object" in str(exc.value)


def test_mixed_list() -> None:
    """Create a list containing one remote and one inline tool."""
    data = {
        "id": "agent-4",
        "name": "Mixed Agent",
        "role": "Worker",
        "goal": "Work",
        "tools": [
            {"type": "remote", "uri": "mcp://remote"},
            {"type": "inline", "name": "local_tool", "description": "Local", "parameters": {"type": "object"}},
        ],
    }
    agent = AgentDefinition.model_validate(data)
    assert len(agent.tools) == 2
    assert isinstance(agent.tools[0], ToolRequirement)
    assert agent.tools[0].uri == "mcp://remote"

    assert isinstance(agent.tools[1], InlineToolDefinition)
    assert agent.tools[1].name == "local_tool"


def test_tools_validation_non_list() -> None:
    """Verify validation when tools is not a list."""
    data = {
        "id": "agent-6",
        "name": "Invalid Tools Agent",
        "role": "Worker",
        "goal": "Work",
        "tools": "not-a-list",
    }
    with pytest.raises(ValidationError) as exc:
        AgentDefinition.model_validate(data)
    assert "Input should be a valid list" in str(exc.value)


def test_tools_validation_invalid_item() -> None:
    """Verify validation when tools contains an invalid item (not str/dict)."""
    data = {
        "id": "agent-7",
        "name": "Invalid Item Agent",
        "role": "Worker",
        "goal": "Work",
        "tools": [123],  # Invalid item type
    }
    with pytest.raises(ValidationError) as exc:
        AgentDefinition.model_validate(data)
    # The validator passes 123 through, Pydantic raises validation error for the item
    assert "Input should be a valid dictionary" in str(exc.value)
