import importlib
import shutil
import sys
import zipfile
from pathlib import Path


SCRIPT_DIR = Path("nanobot/skills/skill-creator/scripts").resolve()
if str(SCRIPT_DIR) not in sys.path:
    sys.path.insert(0, str(SCRIPT_DIR))

init_skill = importlib.import_module("init_skill")
package_skill = importlib.import_module("package_skill")
quick_validate = importlib.import_module("quick_validate")


def test_init_skill_creates_expected_files(tmp_path: Path) -> None:
    skill_dir = init_skill.init_skill(
        "demo-skill",
        tmp_path,
        ["scripts", "references", "assets"],
        include_examples=True,
    )

    assert skill_dir == tmp_path / "demo-skill"
    assert (skill_dir / "SKILL.md").exists()
    assert (skill_dir / "scripts" / "example.py").exists()
    assert (skill_dir / "references" / "api_reference.md").exists()
    assert (skill_dir / "assets" / "example_asset.txt").exists()


def test_validate_skill_accepts_existing_skill_creator() -> None:
    valid, message = quick_validate.validate_skill(
        Path("nanobot/skills/skill-creator").resolve()
    )

    assert valid, message


def test_validate_skill_rejects_placeholder_description(tmp_path: Path) -> None:
    skill_dir = tmp_path / "placeholder-skill"
    skill_dir.mkdir()
    (skill_dir / "SKILL.md").write_text(
        "---\n"
        "name: placeholder-skill\n"
        'description: "[TODO: fill me in]"\n'
        "---\n"
        "# Placeholder\n",
        encoding="utf-8",
    )

    valid, message = quick_validate.validate_skill(skill_dir)

    assert not valid
    assert "TODO placeholder" in message


def test_validate_skill_rejects_root_files_outside_allowed_dirs(tmp_path: Path) -> None:
    skill_dir = tmp_path / "bad-root-skill"
    skill_dir.mkdir()
    (skill_dir / "SKILL.md").write_text(
        "---\n"
        "name: bad-root-skill\n"
        "description: Valid description\n"
        "---\n"
        "# Skill\n",
        encoding="utf-8",
    )
    (skill_dir / "README.md").write_text("extra\n", encoding="utf-8")

    valid, message = quick_validate.validate_skill(skill_dir)

    assert not valid
    assert "Unexpected file or directory in skill root" in message


def test_package_skill_creates_archive(tmp_path: Path) -> None:
    skill_dir = tmp_path / "package-me"
    skill_dir.mkdir()
    (skill_dir / "SKILL.md").write_text(
        "---\n"
        "name: package-me\n"
        "description: Package this skill.\n"
        "---\n"
        "# Skill\n",
        encoding="utf-8",
    )
    scripts_dir = skill_dir / "scripts"
    scripts_dir.mkdir()
    (scripts_dir / "helper.py").write_text("print('ok')\n", encoding="utf-8")

    archive_path = package_skill.package_skill(skill_dir, tmp_path / "dist")

    assert archive_path == (tmp_path / "dist" / "package-me.skill")
    assert archive_path.exists()
    with zipfile.ZipFile(archive_path, "r") as archive:
        names = set(archive.namelist())
    assert "package-me/SKILL.md" in names
    assert "package-me/scripts/helper.py" in names


def test_package_skill_rejects_symlink(tmp_path: Path) -> None:
    skill_dir = tmp_path / "symlink-skill"
    skill_dir.mkdir()
    (skill_dir / "SKILL.md").write_text(
        "---\n"
        "name: symlink-skill\n"
        "description: Reject symlinks during packaging.\n"
        "---\n"
        "# Skill\n",
        encoding="utf-8",
    )
    scripts_dir = skill_dir / "scripts"
    scripts_dir.mkdir()
    target = tmp_path / "outside.txt"
    target.write_text("secret\n", encoding="utf-8")
    link = scripts_dir / "outside.txt"

    try:
        link.symlink_to(target)
    except (OSError, NotImplementedError):
        return

    archive_path = package_skill.package_skill(skill_dir, tmp_path / "dist")

    assert archive_path is None
    assert not (tmp_path / "dist" / "symlink-skill.skill").exists()
