#!/usr/bin/env python3
"""
Functional tests for Tool Synthesis and Quality Reporting modules.
"""

import asyncio
import json
import os
import sys
import tempfile
from pathlib import Path

sys.path.insert(0, os.path.dirname(__file__))


# ============================================================================
# TEST 1: Tool Synthesis - GeneratedToolStore
# ============================================================================


def test_tool_store_save_and_retrieve():
    """Test GeneratedToolStore basic save/retrieve operations."""
    from logos_adk.tool_synthesis import GeneratedToolStore, GeneratedToolArtifact

    with tempfile.TemporaryDirectory() as tmpdir:
        store = GeneratedToolStore(tmpdir)

        source_code = '''
def run(query: str) -> str:
    """Search the web."""
    return f"Results for: {query}"
'''

        tests = """
def test_run():
    result = run("test")
    assert "test" in result
"""

        artifact = store.save_tool(
            name="web_search",
            description="A tool to search the web",
            parameters={
                "type": "object",
                "properties": {"query": {"type": "string", "description": "Search query"}},
                "required": ["query"],
            },
            source_code=source_code,
            tests=tests,
            created_by="test_agent",
        )

        assert artifact.name == "web_search"
        assert artifact.description == "A tool to search the web"
        assert artifact.created_by == "test_agent"

        retrieved = store.get_artifact("web_search")
        assert retrieved.name == artifact.name
        assert retrieved.description == artifact.description

        tools = store.list_tools()
        assert "web_search" in tools

        print("✓ test_tool_store_save_and_retrieve PASSED")
        return True


def test_tool_store_multiple_tools():
    """Test storing multiple tools."""
    from logos_adk.tool_synthesis import GeneratedToolStore

    with tempfile.TemporaryDirectory() as tmpdir:
        store = GeneratedToolStore(tmpdir)

        for i in range(3):
            store.save_tool(
                name=f"tool_{i}",
                description=f"Tool number {i}",
                parameters={"type": "object", "properties": {}, "required": []},
                source_code="def run():\n    return 'ok'",
                tests="def test_run():\n    assert run() == 'ok'",
            )

        tools = store.list_tools()
        assert len(tools) == 3
        assert "tool_0" in tools
        assert "tool_1" in tools
        assert "tool_2" in tools

        print("✓ test_tool_store_multiple_tools PASSED")
        return True


def test_tool_store_bindings():
    """Test agent/team bindings."""
    from logos_adk.tool_synthesis import GeneratedToolStore

    with tempfile.TemporaryDirectory() as tmpdir:
        store = GeneratedToolStore(tmpdir)

        store.save_tool(
            name="search",
            description="Search tool",
            parameters={"type": "object", "properties": {}, "required": []},
            source_code="def run():\n    return 'ok'",
            tests="def test_run():\n    pass",
        )

        store.bind_tool_to_agent("search", "my_agent")
        store.bind_tool_to_team("search", "my_team")

        store.save_tool(
            name="calculate",
            description="Calc tool",
            parameters={"type": "object", "properties": {}, "required": []},
            source_code="def run():\n    return 'ok'",
            tests="def test_run():\n    pass",
        )

        store.bind_tool_to_agent("calculate", "my_agent")

        bindings_path = Path(tmpdir) / "bindings.json"
        assert bindings_path.exists()

        with open(bindings_path) as f:
            bindings = json.load(f)

        assert "my_agent" in bindings.get("agents", {})
        assert "my_team" in bindings.get("teams", {})
        assert "search" in bindings["agents"]["my_agent"]
        assert "calculate" in bindings["agents"]["my_agent"]
        assert "search" in bindings["teams"]["my_team"]

        print("✓ test_tool_store_bindings PASSED")
        return True


def test_tool_name_normalization():
    """Test tool name normalization."""
    from logos_adk.tool_synthesis import GeneratedToolStore

    with tempfile.TemporaryDirectory() as tmpdir:
        store = GeneratedToolStore(tmpdir)

        # Test valid name that gets normalized
        store.save_tool(
            name="my_tool",
            description="Test",
            parameters={"type": "object", "properties": {}, "required": []},
            source_code="def run():\n    return 'ok'",
            tests="def test_run():\n    pass",
        )

        tools = store.list_tools()
        assert "my_tool" in tools

        retrieved = store.get_artifact("my_tool")
        assert retrieved.name == "my_tool"

        print("✓ test_tool_name_normalization PASSED")
        return True


def test_tool_store_validation():
    """Test that invalid code is rejected."""
    from logos_adk.tool_synthesis import GeneratedToolStore

    with tempfile.TemporaryDirectory() as tmpdir:
        store = GeneratedToolStore(tmpdir)

        try:
            store.save_tool(
                name="bad_tool",
                description="Bad tool",
                parameters={},
                source_code="def run():\n    undefined_var",
                tests="def test_run():\n    pass",
            )
            print("✗ test_tool_store_validation should have failed")
            return False
        except Exception as e:
            print(
                f"✓ test_tool_store_validation PASSED (correctly rejected invalid code: {type(e).__name__})"
            )
            return True


# ============================================================================
# TEST 2: Quality Reporting
# ============================================================================


def test_quality_report_html():
    """Test HTML report generation."""
    from logos_adk.quality_report import generate_quality_report_html

    html = generate_quality_report_html(
        title="Test Report",
        summary={"total": 10, "passed": 8, "failed": 2},
        sections=[
            {
                "title": "Test Results",
                "columns": ["name", "status", "duration"],
                "rows": [
                    {"name": "test_1", "status": True, "duration": "0.5s"},
                    {"name": "test_2", "status": False, "duration": "1.2s"},
                ],
            }
        ],
    )

    assert "Test Report" in html
    assert "total" in html.lower()
    assert "passed" in html.lower()
    assert "<!DOCTYPE html>" in html
    assert "test_1" in html
    assert "test_2" in html

    print("✓ test_quality_report_html PASSED")
    return True


def test_quality_report_markdown():
    """Test Markdown report generation."""
    from logos_adk.quality_report import generate_quality_report_markdown

    md = generate_quality_report_markdown(
        title="Test Report",
        summary={"total": 10, "passed": 8},
        sections=[
            {
                "title": "Results",
                "columns": ["name", "status"],
                "rows": [
                    {"name": "test_1", "status": "pass"},
                    {"name": "test_2", "status": "fail"},
                ],
            }
        ],
    )

    assert "# Test Report" in md
    assert "## Summary" in md
    assert "**total**: 10" in md
    assert "## Results" in md
    assert "| name | status |" in md
    assert "| test_1 | pass |" in md

    print("✓ test_quality_report_markdown PASSED")
    return True


def test_quality_report_csv():
    """Test CSV report generation."""
    from logos_adk.quality_report import generate_quality_report_csv

    csv_content = generate_quality_report_csv(
        sections=[
            {
                "title": "Results",
                "columns": ["name", "status"],
                "rows": [
                    {"name": "test_1", "status": "pass"},
                    {"name": "test_2", "status": "fail"},
                ],
            }
        ]
    )

    lines = csv_content.strip().split("\n")
    assert len(lines) == 5
    assert "section" in lines[0]
    assert "test_1" in csv_content
    assert "test_2" in csv_content

    print("✓ test_quality_report_csv PASSED")
    return True


def test_quality_report_write_file():
    """Test writing report to file."""
    from logos_adk.quality_report import write_quality_report_file

    with tempfile.TemporaryDirectory() as tmpdir:
        path = Path(tmpdir) / "report.html"

        write_quality_report_file(
            path,
            title="Test Report",
            summary={"total": 5},
            sections=[{"title": "Tests", "columns": ["name"], "rows": [{"name": "test_1"}]}],
        )

        assert path.exists()
        content = path.read_text()
        assert "Test Report" in content

        md_path = Path(tmpdir) / "report.md"
        write_quality_report_file(md_path, title="MD Report", summary={"total": 3}, sections=[])

        assert md_path.exists()
        md_content = md_path.read_text()
        assert "# MD Report" in md_content

        csv_path = Path(tmpdir) / "report.csv"
        write_quality_report_file(
            csv_path,
            title="CSV Report",
            summary={},
            sections=[{"title": "t", "columns": ["c"], "rows": []}],
        )

        assert csv_path.exists()

        print("✓ test_quality_report_write_file PASSED")
        return True


def test_quality_report_badges():
    """Test badge class generation."""
    from logos_adk.quality_report import _badge_class

    assert _badge_class(True) == "pass"
    assert _badge_class(False) == "fail"
    assert _badge_class("pending") == "neutral"
    assert _badge_class(123) == "neutral"

    print("✓ test_quality_report_badges PASSED")
    return True


def test_quality_report_render_value():
    """Test value rendering."""
    from logos_adk.quality_report import _render_value

    assert _render_value("hello") == "hello"
    assert _render_value(123) == "123"
    assert "<pre>" in _render_value({"key": "value"})
    assert "<pre>" in _render_value([1, 2, 3])

    print("✓ test_quality_report_render_value PASSED")
    return True


# ============================================================================
# TEST 3: Integration - Tool Store with Agent
# ============================================================================


async def test_tool_synthesis_integration():
    """Integration test: create tool, bind to agent."""
    from logos_adk.tool_synthesis import GeneratedToolStore
    from logos_adk.agent import Agent
    from logos_adk.providers.openai import OpenAICompatibleProvider

    with tempfile.TemporaryDirectory() as tmpdir:
        store = GeneratedToolStore(tmpdir)

        tool_source = '''
def run(query: str) -> dict:
    """Execute a search query.
    
    Args:
        query: The search query string.
    
    Returns:
        A dictionary with results.
    """
    return {"results": [f"Result for: {query}"], "count": 1}
'''

        tool_tests = """
def test_run():
    result = run("test")
    assert "results" in result
    assert result["count"] == 1
"""

        artifact = store.save_tool(
            name="integration_search",
            description="Integration test search tool",
            parameters={"query": {"type": "string"}},
            source_code=tool_source,
            tests=tool_tests,
        )

        tool = store.resolve_tool("integration_search")
        assert tool is not None

        print("✓ test_tool_synthesis_integration PASSED")
        return True


# ============================================================================
# MAIN
# ============================================================================


def main():
    print("=" * 70)
    print("TOOL SYNTHESIS & QUALITY REPORTING TESTS")
    print("=" * 70)

    results = []

    tests = [
        ("Tool Store: Save & Retrieve", test_tool_store_save_and_retrieve),
        ("Tool Store: Multiple Tools", test_tool_store_multiple_tools),
        ("Tool Store: Bindings", test_tool_store_bindings),
        ("Tool Store: Name Normalization", test_tool_name_normalization),
        ("Tool Store: Validation", test_tool_store_validation),
        ("Quality Report: HTML", test_quality_report_html),
        ("Quality Report: Markdown", test_quality_report_markdown),
        ("Quality Report: CSV", test_quality_report_csv),
        ("Quality Report: Write File", test_quality_report_write_file),
        ("Quality Report: Badges", test_quality_report_badges),
        ("Quality Report: Render Value", test_quality_report_render_value),
    ]

    for name, test_func in tests:
        try:
            if asyncio.iscoroutinefunction(test_func):
                result = asyncio.run(test_func())
            else:
                result = test_func()
            results.append((name, result))
        except Exception as e:
            print(f"✗ {name}: {e}")
            import traceback

            traceback.print_exc()
            results.append((name, False))

    print("\n" + "=" * 70)
    print("RESULTS")
    print("=" * 70)

    passed = sum(1 for _, ok in results if ok)
    total = len(results)

    for name, ok in results:
        status = "✓ PASS" if ok else "✗ FAIL"
        print(f"{status}: {name}")

    print(f"\n{passed}/{total} tests passed")
    return passed == total


if __name__ == "__main__":
    success = main()
    sys.exit(0 if success else 1)
