#!/usr/bin/env python3
"""Tests for skill validator module."""

import os
import sys
import tempfile
import unittest
from pathlib import Path

sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
from tools.skill_validator import SkillValidator, SkillValidationError


VALID_SKILL = """---
name: test-skill
description: A valid test skill for validation
version: "1.0.0"
author: ezra
tags: [testing, validation]
---

# Test Skill

## Trigger
Use when testing skill validation.

## Steps
1. First step: do something
2. Second step: verify
3. Third step: done

```bash
echo "hello world"
```

## Pitfalls
- Don't forget to test edge cases

## Verification
- Check the output matches expected
"""

MINIMAL_SKILL = """---
name: minimal
description: Minimal skill
version: "1.0"
---

## Trigger
When needed.

## Steps
1. Do it.
2. Done.
"""

BROKEN_SKILL_NO_FM = """# No Frontmatter Skill

## Steps
1. This will fail validation
"""

BROKEN_SKILL_BAD_YAML = """---
name: [invalid yaml
---

## Steps
1. test
"""

BROKEN_SKILL_MISSING_FIELDS = """---
description: Missing name and version
---

## Steps
1. test
"""


class TestSkillValidationError(unittest.TestCase):
    def test_repr_error(self):
        e = SkillValidationError("ERROR", "bad thing", "frontmatter")
        self.assertIn("❌", repr(e))
        self.assertIn("bad thing", repr(e))

    def test_repr_warning(self):
        e = SkillValidationError("WARNING", "maybe bad")
        self.assertIn("⚠️", repr(e))

    def test_repr_info(self):
        e = SkillValidationError("INFO", "just fyi")
        self.assertIn("ℹ️", repr(e))


class TestSkillValidator(unittest.TestCase):
    def setUp(self):
        self.validator = SkillValidator()
        self.tmp_dir = tempfile.mkdtemp()

    def tearDown(self):
        import shutil
        shutil.rmtree(self.tmp_dir, ignore_errors=True)

    def _write_skill(self, content: str, name: str = "test-skill") -> Path:
        skill_dir = Path(self.tmp_dir) / name
        skill_dir.mkdir(parents=True, exist_ok=True)
        path = skill_dir / "SKILL.md"
        path.write_text(content)
        return path

    def test_valid_skill_no_errors(self):
        path = self._write_skill(VALID_SKILL)
        errors = self.validator.validate_file(path)
        error_count = len([e for e in errors if e.level == "ERROR"])
        self.assertEqual(error_count, 0, f"Unexpected errors: {errors}")

    def test_minimal_skill_warnings_only(self):
        path = self._write_skill(MINIMAL_SKILL, "minimal")
        errors = self.validator.validate_file(path)
        error_count = len([e for e in errors if e.level == "ERROR"])
        self.assertEqual(error_count, 0)
        # Should have warnings for missing recommended sections
        warning_count = len([e for e in errors if e.level == "WARNING"])
        self.assertGreater(warning_count, 0)

    def test_no_frontmatter_error(self):
        path = self._write_skill(BROKEN_SKILL_NO_FM, "broken1")
        errors = self.validator.validate_file(path)
        fm_errors = [e for e in errors if "frontmatter" in e.field and e.level == "ERROR"]
        self.assertGreater(len(fm_errors), 0)

    def test_bad_yaml_error(self):
        path = self._write_skill(BROKEN_SKILL_BAD_YAML, "broken2")
        errors = self.validator.validate_file(path)
        yaml_errors = [e for e in errors if "YAML" in e.message or "frontmatter" in e.field]
        self.assertGreater(len(yaml_errors), 0)

    def test_missing_required_fields(self):
        path = self._write_skill(BROKEN_SKILL_MISSING_FIELDS, "broken3")
        errors = self.validator.validate_file(path)
        missing = [e for e in errors if "Missing required" in e.message]
        self.assertGreater(len(missing), 0)

    def test_file_not_found(self):
        errors = self.validator.validate_file(Path("/nonexistent/SKILL.md"))
        self.assertEqual(len(errors), 1)
        self.assertEqual(errors[0].level, "ERROR")

    def test_empty_file(self):
        path = self._write_skill("", "empty")
        errors = self.validator.validate_file(path)
        self.assertTrue(any(e.message == "File is empty" for e in errors))

    def test_invalid_name_format(self):
        skill = """---
name: BAD NAME!
description: test
version: "1.0"
---
## Trigger
test
## Steps
1. test
2. done
"""
        path = self._write_skill(skill, "badname")
        errors = self.validator.validate_file(path)
        name_errors = [e for e in errors if "Invalid name" in e.message]
        self.assertGreater(len(name_errors), 0)

    def test_validate_all(self):
        self._write_skill(VALID_SKILL, "skill-a")
        self._write_skill(MINIMAL_SKILL, "skill-b")
        results = self.validator.validate_all(Path(self.tmp_dir))
        self.assertEqual(len(results), 2)
        self.assertIn("skill-a", results)
        self.assertIn("skill-b", results)

    def test_format_report(self):
        self._write_skill(VALID_SKILL, "good")
        self._write_skill(BROKEN_SKILL_NO_FM, "bad")
        results = self.validator.validate_all(Path(self.tmp_dir))
        report = self.validator.format_report(results)
        self.assertIn("Skill Validation Report", report)
        self.assertIn("good", report)
        self.assertIn("bad", report)

    def test_nonstandard_subdir_warning(self):
        skill_dir = Path(self.tmp_dir) / "weirdskill"
        skill_dir.mkdir()
        (skill_dir / "SKILL.md").write_text(VALID_SKILL)
        (skill_dir / "random_dir").mkdir()
        errors = self.validator.validate_file(skill_dir / "SKILL.md")
        dir_warnings = [e for e in errors if "Non-standard" in e.message]
        self.assertGreater(len(dir_warnings), 0)


if __name__ == "__main__":
    unittest.main()
