"""NUMA sub-client — signal relay, hints, forecasts, and coordination."""

from __future__ import annotations

from typing import Any, Mapping, Sequence

from sbn._http import HttpTransport

_VALID_SIGNAL_TYPES = {
    "GEC_HEALTH",
    "PRIORITY_SHIFT",
    "GOVERNANCE_ALERT",
    "ESCALATION",
    "FORECAST",
    "INSTRUCTION",
    "META",
    "AUDIT",
}

_LANE_NAMES = {"gec_health", "forecast", "control"}


class NUMAClient:
    """Signal relay, hints, forecasts, and telemetry for NUMA integration."""

    def __init__(self, transport: HttpTransport) -> None:
        self._t = transport

    # ── Signals ─────────────────────────────────────────────────────────

    def publish_signals(
        self,
        signals: Sequence[Mapping[str, Any]],
    ) -> dict[str, Any]:
        """Publish a batch of signals to SBN for relay.

        Endpoint: ``POST /internal/numa/signals``

        Each signal dict should contain ``signal_id``, ``signal_type``,
        ``priority``, ``frontier_id``, ``payload``, ``expires_at``,
        ``created_at``.

        Triggers auto-distillation on the server side.
        """
        body: dict[str, Any] = {"signals": [dict(s) for s in signals]}
        return self._t.post("/internal/numa/signals", json=body).json()

    def get_signals(
        self,
        *,
        signal_type: str | None = None,
        frontier_id: str | None = None,
        active_only: bool = True,
        since: str | None = None,
        lane: str | None = None,
        limit: int = 100,
    ) -> dict[str, Any]:
        """Query cached signals.

        Endpoint: ``GET /internal/numa/signals``

        Args:
            signal_type: Filter by signal type.
            frontier_id: Filter by frontier.
            active_only: Only return non-expired signals (default True).
            since: ISO-8601 cursor — only signals created after this time.
            lane: Filter by poll lane (``gec_health``, ``forecast``, ``control``).
            limit: Max signals to return (default 100).

        Returns:
            ``{"signals": [...], "cursor": "ISO-8601", "count": N}``
        """
        params: dict[str, str] = {"limit": str(limit)}
        if signal_type:
            params["signal_type"] = signal_type
        if frontier_id:
            params["frontier_id"] = frontier_id
        if not active_only:
            params["active_only"] = "false"
        if since:
            params["since"] = since
        if lane:
            params["lane"] = lane
        return self._t.get("/internal/numa/signals", params=params).json()

    def poll_signals_multilane(
        self,
        *,
        cursors: Mapping[str, str | None],
        frontier_id: str | None = None,
        limit_per_lane: int = 10,
    ) -> dict[str, Any]:
        """Multi-lane cursor poll for efficient signal consumption.

        Endpoint: ``POST /internal/numa/signals/poll``

        Args:
            cursors: Mapping of lane name to ISO-8601 cursor (or None for
                     all signals). Lanes: ``gec_health``, ``forecast``,
                     ``control``.
            frontier_id: Optional frontier filter.
            limit_per_lane: Max signals per lane (default 10).

        Returns:
            ``{"lanes": [{"lane": "...", "signals": [...],
              "cursor": "ISO-8601", "count": N}, ...]}``
        """
        lane_cursors = [
            {"lane": lane, "since": since}
            for lane, since in cursors.items()
        ]
        body: dict[str, Any] = {
            "cursors": lane_cursors,
            "limit_per_lane": limit_per_lane,
        }
        if frontier_id:
            body["frontier_id"] = frontier_id
        return self._t.post("/internal/numa/signals/poll", json=body).json()

    def ack_signals(
        self,
        signal_ids: Sequence[str],
        *,
        agent_id: str | None = None,
    ) -> dict[str, Any]:
        """Acknowledge signal delivery.

        Endpoint: ``POST /internal/numa/signals/ack``

        Args:
            signal_ids: List of signal IDs to acknowledge.
            agent_id: Optional agent identifier for audit.
        """
        body: dict[str, Any] = {"signal_ids": list(signal_ids)}
        if agent_id:
            body["agent_id"] = agent_id
        return self._t.post("/internal/numa/signals/ack", json=body).json()

    # ── Hints ───────────────────────────────────────────────────────────

    def publish_hints(
        self,
        hints: Sequence[Mapping[str, Any]],
    ) -> dict[str, Any]:
        """Publish pre-distilled hints to SBN.

        Endpoint: ``POST /internal/numa/hints``
        """
        body: dict[str, Any] = {"hints": [dict(h) for h in hints]}
        return self._t.post("/internal/numa/hints", json=body).json()

    def get_hints(
        self,
        *,
        frontier_id: str | None = None,
    ) -> dict[str, Any]:
        """Read distilled hints (plan-gated visibility).

        Endpoint: ``GET /api/numa/hints``

        Args:
            frontier_id: Optional frontier filter.
        """
        params: dict[str, str] = {}
        if frontier_id:
            params["frontier_id"] = frontier_id
        return self._t.get("/api/numa/hints", params=params).json()

    # ── Forecasts ───────────────────────────────────────────────────────

    def publish_forecast(
        self,
        *,
        frontier_id: str,
        report: Mapping[str, Any],
        generated_at: str | None = None,
    ) -> dict[str, Any]:
        """Publish a forecast report for a frontier.

        Endpoint: ``POST /internal/numa/forecast``
        """
        body: dict[str, Any] = {
            "frontier_id": frontier_id,
            "report": dict(report),
        }
        if generated_at:
            body["generated_at"] = generated_at
        return self._t.post("/internal/numa/forecast", json=body).json()

    def get_forecast(self, frontier_id: str) -> dict[str, Any]:
        """Get the latest forecast report for a frontier.

        Endpoint: ``GET /internal/numa/forecast/{frontier_id}``
        """
        return self._t.get(f"/internal/numa/forecast/{frontier_id}").json()

    def list_forecasts(self) -> dict[str, Any]:
        """List all forecast reports (summary per frontier).

        Endpoint: ``GET /internal/numa/forecast``
        """
        return self._t.get("/internal/numa/forecast").json()

    # ── Diagnostics ─────────────────────────────────────────────────────

    def get_diagnostics(self) -> dict[str, Any]:
        """Per-frontier CSK analysis for sbn-web.

        Endpoint: ``GET /api/numa/diagnostics``
        """
        return self._t.get("/api/numa/diagnostics").json()
