"""Tests for activity bus handler registry."""
from __future__ import annotations

import pytest
from collections import defaultdict

from shared.events.bus import (
    register_activity_handler,
    get_activity_handlers,
    _activity_handlers,
)


@pytest.fixture(autouse=True)
def _clean_handlers():
    """Clear handler registry before each test."""
    _activity_handlers.clear()
    yield
    _activity_handlers.clear()


# Dummy handlers
async def handler_a(activity, session):
    pass

async def handler_b(activity, session):
    pass

async def handler_c(activity, session):
    pass

async def handler_global(activity, session):
    pass


# ---------------------------------------------------------------------------
# register_activity_handler
# ---------------------------------------------------------------------------

class TestRegisterHandler:
    def test_register_with_type_only(self):
        register_activity_handler("Create", handler_a)
        assert ("Create", "*") in _activity_handlers
        assert handler_a in _activity_handlers[("Create", "*")]

    def test_register_with_object_type(self):
        register_activity_handler("Create", handler_a, object_type="Note")
        assert ("Create", "Note") in _activity_handlers

    def test_multiple_handlers_same_key(self):
        register_activity_handler("Create", handler_a)
        register_activity_handler("Create", handler_b)
        assert len(_activity_handlers[("Create", "*")]) == 2

    def test_wildcard_type(self):
        register_activity_handler("*", handler_global)
        assert ("*", "*") in _activity_handlers


# ---------------------------------------------------------------------------
# get_activity_handlers — cascading wildcard lookup
# ---------------------------------------------------------------------------

class TestGetHandlers:
    def test_exact_match(self):
        register_activity_handler("Create", handler_a, object_type="Note")
        handlers = get_activity_handlers("Create", "Note")
        assert handler_a in handlers

    def test_type_wildcard_match(self):
        register_activity_handler("Create", handler_a)  # key: ("Create", "*")
        handlers = get_activity_handlers("Create", "Note")
        assert handler_a in handlers

    def test_global_wildcard_match(self):
        register_activity_handler("*", handler_global)  # key: ("*", "*")
        handlers = get_activity_handlers("Create", "Note")
        assert handler_global in handlers

    def test_cascading_order(self):
        """Handlers should come in order: exact → type-wildcard → global-wildcard."""
        register_activity_handler("Create", handler_a, object_type="Note")  # exact
        register_activity_handler("Create", handler_b)  # type-wildcard
        register_activity_handler("*", handler_c)  # global wildcard

        handlers = get_activity_handlers("Create", "Note")
        assert handlers == [handler_a, handler_b, handler_c]

    def test_no_match(self):
        register_activity_handler("Create", handler_a, object_type="Note")
        handlers = get_activity_handlers("Delete", "Article")
        assert handlers == []

    def test_no_object_type_skips_exact(self):
        register_activity_handler("Create", handler_a, object_type="Note")
        register_activity_handler("Create", handler_b)
        handlers = get_activity_handlers("Create")
        # Should get type-wildcard only (since object_type defaults to "*")
        assert handler_b in handlers
        assert handler_a not in handlers

    def test_global_wildcard_not_duplicated(self):
        """Global wildcard should not fire when activity_type is already '*'."""
        register_activity_handler("*", handler_global)
        handlers = get_activity_handlers("*")
        # Should not include global wildcard twice
        assert handlers.count(handler_global) == 1

    def test_type_wildcard_plus_global(self):
        register_activity_handler("Follow", handler_a)
        register_activity_handler("*", handler_global)
        handlers = get_activity_handlers("Follow")
        assert handler_a in handlers
        assert handler_global in handlers

    def test_only_global_wildcard(self):
        register_activity_handler("*", handler_global)
        handlers = get_activity_handlers("Like", "Post")
        assert handlers == [handler_global]
