"""End-to-end tests: multi-skill chaining and discovery."""

import os
from pathlib import Path

from fliiq.runtime.agent.tools import ToolRegistry
from fliiq.runtime.package_data import bundled_skills_dir
from fliiq.runtime.skills.base import SkillBase
from fliiq.runtime.skills.loader import discover_skills

PROJECT_ROOT = Path(os.path.dirname(__file__)).parent
SKILLS_DIR = bundled_skills_dir()


def test_discover_all_skills():
    """All 10 skills discovered from project root."""
    skills = discover_skills(project_root=PROJECT_ROOT)
    assert len(skills) >= 10
    expected = {
        "read_file", "write_file", "edit_file", "list_directory",
        "grep", "find", "shell", "web_search",
        "get_current_time", "fetch_html",
    }
    assert expected.issubset(set(skills.keys())), f"Missing: {expected - set(skills.keys())}"


def test_register_all_skills():
    """All discovered skills can be registered in ToolRegistry."""
    skills = discover_skills(project_root=PROJECT_ROOT)
    tools = ToolRegistry()
    for skill in skills.values():
        tools.register_skill(skill)
    tools.register_builtins()

    defs = tools.get_tool_definitions()
    names = {d["name"] for d in defs}
    # 10 skills + 2 builtins (todo, ask_user)
    assert len(names) >= 12
    assert "read_file" in names
    assert "shell" in names
    assert "get_current_time" in names
    assert "todo" in names


async def test_chain_write_read(tmp_path):
    """Chain write_file -> read_file."""
    write_skill = SkillBase(str(SKILLS_DIR / "write_file"))
    read_skill = SkillBase(str(SKILLS_DIR / "read_file"))

    target = str(tmp_path / "chained.txt")
    await write_skill.execute({"path": target, "content": "chained content"})

    result = await read_skill.execute({"path": target})
    assert "chained content" in result["content"]


async def test_chain_write_edit_read(tmp_path):
    """Chain write_file -> edit_file -> read_file."""
    write = SkillBase(str(SKILLS_DIR / "write_file"))
    edit = SkillBase(str(SKILLS_DIR / "edit_file"))
    read = SkillBase(str(SKILLS_DIR / "read_file"))

    target = str(tmp_path / "edit_chain.txt")
    await write.execute({"path": target, "content": "hello world"})
    await edit.execute({"path": target, "old_text": "hello", "new_text": "goodbye"})

    result = await read.execute({"path": target})
    assert "goodbye world" in result["content"]


async def test_chain_shell_read(tmp_path):
    """Chain shell -> read_file (shell creates a file, read_file reads it)."""
    shell = SkillBase(str(SKILLS_DIR / "shell"))
    read = SkillBase(str(SKILLS_DIR / "read_file"))

    target = str(tmp_path / "from_shell.txt")
    await shell.execute({"command": f"echo 'shell output' > {target}"})

    result = await read.execute({"path": target})
    assert "shell output" in result["content"]


async def test_find_then_grep(tmp_path):
    """Chain find -> grep."""
    find_skill = SkillBase(str(SKILLS_DIR / "find"))
    grep_skill = SkillBase(str(SKILLS_DIR / "grep"))

    (tmp_path / "a.py").write_text("def foo(): pass\n")
    (tmp_path / "b.py").write_text("def bar(): pass\n")
    (tmp_path / "c.txt").write_text("not python\n")

    found = await find_skill.execute({"pattern": "*.py", "path": str(tmp_path)})
    assert "a.py" in found["files"]

    grepped = await grep_skill.execute({"pattern": "def \\w+", "path": str(tmp_path)})
    assert "foo" in grepped["matches"]
    assert "bar" in grepped["matches"]
