"""Widget registry — modules register widgets via the @register decorator.

Resolution at request time:
    widgets = registry.for_user(user)   # ordered list of instantiated widgets
"""
from __future__ import annotations

import logging
from typing import Type

from apps.core.dashboard.base import ZONE_ORDER, DashboardWidget

logger = logging.getLogger(__name__)

_REGISTRY: list[Type[DashboardWidget]] = []
_KEYS_SEEN: set[str] = set()


def register(cls: Type[DashboardWidget]) -> Type[DashboardWidget]:
    if not cls.key:
        raise ValueError(f"Widget {cls.__name__} must define a `key`.")
    if cls.key in _KEYS_SEEN:
        return cls
    _KEYS_SEEN.add(cls.key)
    _REGISTRY.append(cls)
    return cls


def all_widgets() -> list[Type[DashboardWidget]]:
    return list(_REGISTRY)


def for_user(user) -> list[DashboardWidget]:
    """Return ordered list of widget *instances* enabled for the given user."""
    enabled: list[DashboardWidget] = []
    for cls in _REGISTRY:
        try:
            if cls.is_enabled(user):
                enabled.append(cls())
        except Exception:  # noqa: BLE001 — never let one widget break the dashboard
            logger.exception("Widget %s.is_enabled raised", cls.__name__)
    enabled.sort(key=lambda w: (ZONE_ORDER.index(w.zone), w.priority, w.key))
    return enabled


def reset_for_tests() -> None:
    _REGISTRY.clear()
    _KEYS_SEEN.clear()
