from __future__ import annotations

import pytest

from leshy.core.registry import Registry, attack_registry, evaluator_registry, target_registry


class TestRegistry:
    def test_register_and_get(self) -> None:
        reg: Registry[object] = Registry("test")
        reg._discovered = True  # skip auto-discovery

        @reg.register("my_plugin")
        class MyPlugin:
            pass

        assert reg.get("my_plugin") is MyPlugin

    def test_get_missing_key(self) -> None:
        reg: Registry[object] = Registry("test")
        reg._discovered = True

        with pytest.raises(KeyError, match="not_registered"):
            reg.get("not_registered")

    def test_create_instance(self) -> None:
        reg: Registry[object] = Registry("test")
        reg._discovered = True

        @reg.register("widget")
        class Widget:
            def __init__(self, color: str = "red") -> None:
                self.color = color

        instance = reg.create("widget", color="blue")
        assert instance.color == "blue"  # type: ignore[attr-defined]

    def test_keys_sorted(self) -> None:
        reg: Registry[object] = Registry("test")
        reg._discovered = True

        @reg.register("zebra")
        class Z:
            pass

        @reg.register("alpha")
        class A:
            pass

        assert reg.keys() == ["alpha", "zebra"]

    def test_overwrite_warning(self, caplog: pytest.LogCaptureFixture) -> None:
        reg: Registry[object] = Registry("test")
        reg._discovered = True

        @reg.register("dup")
        class First:
            pass

        @reg.register("dup")
        class Second:
            pass

        assert reg.get("dup") is Second


class TestAutoDiscovery:
    def test_attack_registry_discovers_attacks(self) -> None:
        keys = attack_registry.keys()
        assert "prompt_injection.direct" in keys
        assert "jailbreak.roleplay" in keys
        assert "data_extraction.system_prompt" in keys
        assert "excessive_agency.tool_injection" in keys
        assert "safety.toxicity" in keys
        assert "dos.context_exhaustion" in keys
        assert len(keys) >= 28

    def test_target_registry_discovers_http(self) -> None:
        assert "http" in target_registry.keys()

    def test_evaluator_registry(self) -> None:
        keys = evaluator_registry.keys()
        assert "pattern" in keys
        assert "llm_judge" in keys
