"""
App-level settings for django-notify-hub.

All configuration is read from ``settings.DJANGO_NOTIFY`` (a dict).
Accessing ``app_settings.<KEY>`` returns the user value or the default.

Example Django settings::

    DJANGO_NOTIFY = {
        "BACKENDS": ["django_notify_hub.backends.FCMBackend"],
        "DEFAULT_CHANNELS": ["fcm"],
        "ASYNC": True,
        "CELERY_QUEUE": "notifications",
        "CELERY_MAX_RETRIES": 3,
        "FCM_CREDENTIALS_FILE": "/path/to/firebase.json",
        "DEFAULT_PRIORITY": "normal",
        "PAGINATION_PAGE_SIZE": 20,
    }
"""
from __future__ import annotations

from typing import Any

from django.conf import settings as django_settings
from django.test.signals import setting_changed


DEFAULTS: dict[str, Any] = {
    # Dotted paths to backend classes to load at startup
    "BACKENDS": ["django_notify_hub.backends.fcm.FCMBackend"],
    # Which channels are active by default (must match backend channel names)
    "DEFAULT_CHANNELS": ["fcm"],
    # Run delivery inside Celery tasks (True) or synchronously (False)
    "ASYNC": True,
    # Celery queue name for notification tasks
    "CELERY_QUEUE": "notifications",
    # Max Celery retry attempts on transient failures
    "CELERY_MAX_RETRIES": 3,
    # Seconds between Celery retries (exponential: delay * 2^attempt)
    "CELERY_RETRY_BACKOFF": 60,
    # Path to Firebase service-account JSON (overrides GOOGLE_APPLICATION_CREDENTIALS env var)
    "FCM_CREDENTIALS_FILE": None,
    # Django Channels layer alias used by the websocket backend
    "WEBSOCKET_LAYER_ALIAS": "default",
    # Event type passed to channel_layer.group_send(...)
    "WEBSOCKET_EVENT_TYPE": "notify.message",
    # Default user-specific group naming convention
    "WEBSOCKET_USER_GROUP_TEMPLATE": "notify.user.{user_id}",
    # Optional dotted path or callable: (recipient, payload) -> str | list[str]
    "WEBSOCKET_GROUP_RESOLVER": None,
    # Default notification priority
    "DEFAULT_PRIORITY": "normal",
    # REST API pagination
    "PAGINATION_PAGE_SIZE": 20,
    "PAGINATION_MAX_PAGE_SIZE": 100,
}

SETTING_KEY = "DJANGO_NOTIFY"


class AppSettings:
    """
    Lazy proxy over ``django.conf.settings.DJANGO_NOTIFY``.

    Attribute access pattern::

        from django_notify_hub.conf import app_settings
        app_settings.ASYNC          # True / False
        app_settings.CELERY_QUEUE   # "notifications"
    """

    def __init__(self, defaults: dict[str, Any]) -> None:
        self._defaults = defaults
        self._cached: dict[str, Any] = {}

    # ── Internal helpers ──────────────────────────────────────────────────

    @property
    def _user_settings(self) -> dict[str, Any]:
        return getattr(django_settings, SETTING_KEY, {})

    def _get(self, key: str) -> Any:
        if key not in self._cached:
            self._cached[key] = self._user_settings.get(key, self._defaults[key])
        return self._cached[key]

    def __getattr__(self, key: str) -> Any:
        if key.startswith("_") or key not in self._defaults:
            raise AttributeError(f"Invalid setting: '{key}'")
        return self._get(key)

    def reload(self) -> None:
        """Clear the cache so next access re-reads from Django settings."""
        self._cached.clear()


app_settings = AppSettings(DEFAULTS)


def _reload_on_change(*, setting: str, **_kwargs: Any) -> None:
    if setting == SETTING_KEY:
        app_settings.reload()


setting_changed.connect(_reload_on_change)

