# retoor <retoor@molodetz.nl>

import logging
from typing import Any

from devplacepy.push.providers.apns import ApnsProvider
from devplacepy.push.providers.base import (
    ACCEPTED,
    DEAD,
    REJECTED,
    Delivery,
    PushProvider,
)
from devplacepy.push.providers.webpush import WebPushProvider

logger = logging.getLogger(__name__)

DEFAULT_PROVIDER = WebPushProvider.name

PROVIDERS: dict[str, PushProvider] = {
    provider.name: provider for provider in (WebPushProvider(), ApnsProvider())
}

__all__ = [
    "ACCEPTED",
    "DEAD",
    "DEFAULT_PROVIDER",
    "Delivery",
    "PROVIDERS",
    "PushProvider",
    "REJECTED",
    "active",
    "admin_fields",
    "client_config",
    "get",
    "is_active",
    "names",
    "shutdown",
]


def get(name: str | None) -> PushProvider | None:
    if not isinstance(name, str):
        name = ""
    return PROVIDERS.get(name.strip().lower() or DEFAULT_PROVIDER)


def names() -> list[str]:
    return list(PROVIDERS)


def active() -> list[PushProvider]:
    return [provider for provider in PROVIDERS.values() if is_active(provider)]


def admin_fields() -> list:
    return [field for provider in PROVIDERS.values() for field in provider.all_fields()]


def client_config() -> dict[str, Any]:
    return {provider.name: _client_config(provider) for provider in active()}


def is_active(provider: PushProvider) -> bool:
    try:
        return provider.is_active()
    except Exception as exc:
        logger.error("Push provider %s failed its readiness check: %s", provider.name, exc)
        return False


def _client_config(provider: PushProvider) -> dict[str, Any]:
    try:
        return provider.client_config()
    except Exception as exc:
        logger.error("Push provider %s failed to describe itself: %s", provider.name, exc)
        return {}


async def shutdown() -> None:
    for provider in PROVIDERS.values():
        try:
            await provider.aclose()
        except Exception as exc:
            logger.error("Push provider %s failed to close: %s", provider.name, exc)
