"""Tests for autonomous tool synthesis."""
from __future__ import annotations

import pytest

from logos_adk.agent import Agent
from logos_adk.team import Team
from logos_adk.tool_synthesis import GeneratedToolStore, develop_tool
from logos_adk.tools.config import load_tools_from_config


def _parameter_schema() -> dict[str, object]:
    return {
        "type": "object",
        "properties": {
            "text": {"type": "string"},
        },
        "required": ["text"],
    }


def _source_code() -> str:
    return (
        "async def run(text: str):\n"
        "    words = [part for part in text.split() if part]\n"
        "    return {'words': len(words), 'uppercase': text.upper()}\n"
    )


def _tests_code() -> str:
    return (
        "async def run_tests():\n"
        "    result = await module.run(text='summer sale launch')\n"
        "    assert result == {'words': 3, 'uppercase': 'SUMMER SALE LAUNCH'}\n"
    )


@pytest.mark.asyncio
async def test_develop_tool_persists_and_restores_agent_scope(tmp_path, monkeypatch):
    monkeypatch.setenv("LOGOS_ADK_GENERATED_TOOLS_DIR", str(tmp_path / "generated-tools"))

    creator = Agent("builder")
    result = await develop_tool(
        name="seo_word_count",
        description="Count words in SEO copy and return normalized metadata.",
        parameters=_parameter_schema(),
        source_code=_source_code(),
        tests=_tests_code(),
        self=creator,
    )

    assert result["status"] == "installed"
    assert result["tool_name"] == "seo_word_count"
    assert result["installed_on"] == ["builder"]
    assert "seo_word_count" in [tool.name for tool in creator._config.tools]

    created_tool = next(tool for tool in creator._config.tools if tool.name == "seo_word_count")
    created_result = await created_tool(text="launch copy")
    assert created_result == {"words": 2, "uppercase": "LAUNCH COPY"}

    recreated = Agent("builder")
    restored_tool = next(tool for tool in recreated._config.tools if tool.name == "seo_word_count")
    restored_result = await restored_tool(text="evergreen ad")
    assert restored_result == {"words": 2, "uppercase": "EVERGREEN AD"}


@pytest.mark.asyncio
async def test_develop_tool_persists_and_restores_team_scope(tmp_path, monkeypatch):
    monkeypatch.setenv("LOGOS_ADK_GENERATED_TOOLS_DIR", str(tmp_path / "generated-tools"))

    strategist = Agent("strategist")
    analyst = Agent("analyst")
    Team("growth", agents=[strategist, analyst], topology="mesh")

    result = await develop_tool(
        name="campaign_slug",
        description="Normalize campaign text into a slug.",
        parameters=_parameter_schema(),
        source_code=(
            "def run(text: str):\n"
            "    return {'slug': '-'.join(part.lower() for part in text.split() if part)}\n"
        ),
        tests=(
            "def run_tests():\n"
            "    result = module.run(text='Spring Launch Plan')\n"
            "    assert result == {'slug': 'spring-launch-plan'}\n"
        ),
        scope="team",
        self=strategist,
    )

    assert result["scope"] == "team"
    assert set(result["installed_on"]) == {"strategist", "analyst"}
    assert "campaign_slug" in [tool.name for tool in strategist._config.tools]
    assert "campaign_slug" in [tool.name for tool in analyst._config.tools]

    recreated_team = Team("growth", agents=[Agent("strategist"), Agent("analyst")], topology="mesh")
    for member in recreated_team._agents.values():
        assert "campaign_slug" in [tool.name for tool in member._config.tools]


def test_load_tools_from_config_resolves_generated_tools(tmp_path, monkeypatch):
    monkeypatch.setenv("LOGOS_ADK_GENERATED_TOOLS_DIR", str(tmp_path / "generated-tools"))

    store = GeneratedToolStore()
    store.save_tool(
        name="generated_lookup",
        description="Lookup a generated SEO phrase.",
        parameters=_parameter_schema(),
        source_code=_source_code(),
        tests=_tests_code(),
        created_by="tester",
    )

    resolved = load_tools_from_config(["generated_lookup"])

    assert [tool.name for tool in resolved] == ["generated_lookup"]


@pytest.mark.asyncio
async def test_develop_tool_rejects_failing_tests_without_persisting(tmp_path, monkeypatch):
    monkeypatch.setenv("LOGOS_ADK_GENERATED_TOOLS_DIR", str(tmp_path / "generated-tools"))

    creator = Agent("builder")
    with pytest.raises(ValueError, match="Generated tool validation failed"):
        await develop_tool(
            name="broken_generated_tool",
            description="Broken tool that should not install.",
            parameters=_parameter_schema(),
            source_code=_source_code(),
            tests=(
                "def run_tests():\n"
                "    assert False, 'expected failure'\n"
            ),
            self=creator,
        )

    store = GeneratedToolStore()
    assert store.list_tools() == []
    assert "broken_generated_tool" not in [tool.name for tool in creator._config.tools]
