"""Tests for the dynamic language registry and parser loading."""

import importlib
import pytest
from astchunk.astchunk_builder import (
    _LANGUAGE_REGISTRY,
    _load_parser,
    register_language,
    get_available_languages,
)


class TestLanguageRegistry:
    def test_registry_has_15_languages(self):
        assert len(_LANGUAGE_REGISTRY) >= 15

    def test_known_languages_present(self):
        expected = {
            "python", "java", "csharp", "typescript",
            "c", "cpp", "go", "rust", "ruby",
            "bash", "kotlin", "scala", "lua", "php", "zig",
        }
        assert expected.issubset(set(_LANGUAGE_REGISTRY.keys()))

    def test_special_cases(self):
        # PHP uses language_php, not language
        assert _LANGUAGE_REGISTRY["php"] == ("tree_sitter_php", "language_php")
        # TypeScript uses language_tsx
        assert _LANGUAGE_REGISTRY["typescript"] == ("tree_sitter_typescript", "language_tsx")
        # C# has non-standard module name
        assert _LANGUAGE_REGISTRY["csharp"] == ("tree_sitter_c_sharp", "language")


class TestLoadParser:
    @pytest.mark.parametrize("language", list(_LANGUAGE_REGISTRY.keys()))
    def test_load_registered_language(self, language):
        module_name, _ = _LANGUAGE_REGISTRY[language]
        try:
            importlib.import_module(module_name)
        except ImportError:
            pytest.skip(f"{module_name} not installed")

        parser = _load_parser(language)
        assert parser is not None

    def test_load_unknown_language_raises(self):
        with pytest.raises(ValueError, match="not installed"):
            _load_parser("nonexistent_language_xyz")

    def test_auto_discovery_for_unknown_language(self):
        """If a language follows the standard convention, it should auto-discover."""
        # python follows the convention: tree_sitter_python.language()
        # Remove from registry temporarily to test auto-discovery
        original = _LANGUAGE_REGISTRY.pop("python", None)
        try:
            parser = _load_parser("python")
            assert parser is not None
        finally:
            if original:
                _LANGUAGE_REGISTRY["python"] = original


class TestRegisterLanguage:
    def test_register_new_language(self):
        register_language("test_lang", "tree_sitter_python", "language")
        assert "test_lang" in _LANGUAGE_REGISTRY
        assert _LANGUAGE_REGISTRY["test_lang"] == ("tree_sitter_python", "language")
        # Cleanup
        del _LANGUAGE_REGISTRY["test_lang"]

    def test_register_overrides_existing(self):
        original = _LANGUAGE_REGISTRY.get("python")
        register_language("python", "tree_sitter_python", "language")
        assert _LANGUAGE_REGISTRY["python"] == ("tree_sitter_python", "language")
        # Restore
        if original:
            _LANGUAGE_REGISTRY["python"] = original


class TestGetAvailableLanguages:
    def test_returns_sorted_list(self):
        available = get_available_languages()
        assert available == sorted(available)

    def test_contains_at_least_python(self):
        """Python tree-sitter parser should always be available in test env."""
        try:
            importlib.import_module("tree_sitter_python")
        except ImportError:
            pytest.skip("tree_sitter_python not installed")
        assert "python" in get_available_languages()
