"""Tests for the @hook decorator and Plugin base class."""

from mellea.plugins.base import Plugin, PluginMeta
from mellea.plugins.decorators import HookMeta, hook
from mellea.plugins.types import PluginMode


class TestHookDecorator:
    def test_hook_attaches_metadata(self):
        @hook("generation_pre_call")
        async def my_hook(payload, ctx):
            pass

        assert hasattr(my_hook, "_mellea_hook_meta")
        meta = my_hook._mellea_hook_meta
        assert isinstance(meta, HookMeta)
        assert meta.hook_type == "generation_pre_call"
        assert meta.mode == PluginMode.SEQUENTIAL
        assert (
            meta.priority is None
        )  # no explicit priority; resolves at registration time

    def test_hook_custom_mode_and_priority(self):
        @hook("component_post_success", mode=PluginMode.AUDIT, priority=10)
        async def my_hook(payload, ctx):
            pass

        meta = my_hook._mellea_hook_meta
        assert meta.mode == PluginMode.AUDIT
        assert meta.priority == 10

    def test_hook_fire_and_forget_mode(self):
        @hook("component_post_success", mode=PluginMode.FIRE_AND_FORGET)
        async def my_hook(payload, ctx):
            pass

        meta = my_hook._mellea_hook_meta
        assert meta.mode == PluginMode.FIRE_AND_FORGET

    def test_hook_preserves_function(self):
        @hook("generation_pre_call")
        async def my_hook(payload, ctx):
            return "result"

        assert my_hook.__name__ == "my_hook"


class TestPluginBaseClass:
    def test_plugin_attaches_metadata(self):
        class MyPlugin(Plugin, name="my-plugin"):
            pass

        assert hasattr(MyPlugin, "_mellea_plugin_meta")
        meta = MyPlugin._mellea_plugin_meta
        assert isinstance(meta, PluginMeta)
        assert meta.name == "my-plugin"
        assert meta.priority == 50

    def test_plugin_custom_priority(self):
        class MyPlugin(Plugin, name="my-plugin", priority=5):
            pass

        assert MyPlugin._mellea_plugin_meta.priority == 5  # type: ignore[attr-defined]

    def test_plugin_preserves_class(self):
        class MyPlugin(Plugin, name="my-plugin"):
            def __init__(self):
                self.value = 42

        instance = MyPlugin()
        assert instance.value == 42

    def test_plugin_has_context_manager(self):
        class MyPlugin(Plugin, name="my-plugin"):
            pass

        assert hasattr(MyPlugin, "__enter__")
        assert hasattr(MyPlugin, "__exit__")
        assert hasattr(MyPlugin, "__aenter__")
        assert hasattr(MyPlugin, "__aexit__")

    def test_plugin_without_name_skips_metadata(self):
        class MyBase(Plugin):
            pass

        assert not hasattr(MyBase, "_mellea_plugin_meta")
