from __future__ import annotations

from collections.abc import Mapping
from typing import Any

from govoplan_core.core.module_management import load_startup_enabled_modules, startup_candidate_module_ids
from govoplan_core.core.modules import ModuleContext
from govoplan_core.core.notifications import NotificationDispatchRequest, notification_dispatch_provider
from govoplan_core.server.registry import available_module_manifests, build_platform_registry


INSTALLER_NOTIFICATION_ACTION_URL = "/admin?section=modules"


def emit_module_installer_notification(
    *,
    session: object,
    registry: object | None,
    tenant_id: str | None,
    request: Mapping[str, object],
    event_kind: str,
    subject: str,
    body_text: str,
    recipient_id: str | None = None,
    priority: int = 5,
) -> bool:
    if not tenant_id:
        return False
    provider = notification_dispatch_provider(registry)
    if provider is None:
        return False
    request_id = str(request.get("request_id") or "")
    if not request_id:
        return False
    provider.enqueue_notification(
        session,
        NotificationDispatchRequest(
            tenant_id=tenant_id,
            source_module="core",
            source_resource_type="module_install_request",
            source_resource_id=request_id,
            event_kind=event_kind,
            channel="inbox",
            recipient_type="user" if recipient_id else None,
            recipient_id=recipient_id,
            subject=subject,
            body_text=body_text,
            action_url=INSTALLER_NOTIFICATION_ACTION_URL,
            priority=priority,
            payload={
                "request_id": request_id,
                "status": request.get("status"),
                "run_id": _result_run_id(request),
            },
            metadata={
                "trace": request.get("trace") if isinstance(request.get("trace"), Mapping) else None,
                "retry_of": request.get("retry_of"),
            },
        ),
        enqueue_delivery=False,
    )
    return True


def build_runtime_notification_registry(settings: object) -> object | None:
    try:
        raw_enabled_modules = load_startup_enabled_modules(str(getattr(settings, "enabled_modules", "") or ""))
        candidate_modules = startup_candidate_module_ids(str(getattr(settings, "enabled_modules", "") or ""), raw_enabled_modules)
        available_modules = available_module_manifests(enabled_modules=candidate_modules, ignore_load_errors=True)
        enabled_modules = load_startup_enabled_modules(str(getattr(settings, "enabled_modules", "") or ""), available=available_modules)
        if "notifications" not in enabled_modules:
            return None
        registry = build_platform_registry(enabled_modules)
        registry.configure_capability_context(ModuleContext(registry=registry, settings=settings))
        return registry
    except Exception:  # noqa: BLE001 - notification bridge must not block installer work.
        return None


def installer_notification_subject(event_kind: str, request: Mapping[str, object]) -> str:
    request_id = str(request.get("request_id") or "unknown")
    status = str(request.get("status") or event_kind.rsplit(".", 1)[-1])
    prefixes = {
        "queued": "Module installer request queued",
        "running": "Module installer request started",
        "completed": "Module installer request completed",
        "failed": "Module installer request failed",
        "cancelled": "Module installer request cancelled",
    }
    prefix = prefixes.get(status, "Module installer request updated")
    return ": ".join((prefix, request_id))


def _installer_status_sentence(request_id: str, status: str) -> str:
    return " ".join(("Installer request", request_id, "is", status))


def installer_notification_body(event_kind: str, request: Mapping[str, object]) -> str:
    status = str(request.get("status") or event_kind.rsplit(".", 1)[-1])
    request_id = str(request.get("request_id") or "unknown")
    result = request.get("result") if isinstance(request.get("result"), Mapping) else {}
    error = str(request.get("error") or result.get("error") or "").strip()
    sentence = _installer_status_sentence(request_id, status)
    if error:
        return ". Error: ".join((sentence, error))
    run_id = _result_run_id(request)
    if run_id:
        return ". Run: ".join((sentence, run_id))
    # This helper returns plain notification text, not an HTTP/HTML response.
    return sentence + "."  # nosemgrep: python.flask.security.audit.directly-returned-format-string.directly-returned-format-string


def installer_notification_priority(status: str) -> int:
    if status == "failed":
        return 20
    if status in {"completed", "cancelled"}:
        return 8
    if status == "running":
        return 4
    return 5


def _result_run_id(request: Mapping[str, object]) -> str | None:
    result = request.get("result") if isinstance(request.get("result"), Mapping) else {}
    run_id: Any = result.get("run_id") if isinstance(result, Mapping) else None
    return str(run_id) if run_id else None
