"""Blocks sub-client — SmartBlock creation, submission, and queries."""

from __future__ import annotations

from typing import Any, Mapping

from sbn._http import HttpTransport


class BlocksClient:
    """Create, submit, and query SmartBlocks."""

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

    def create(
        self,
        *,
        payload: Mapping[str, Any],
        domain: str = "default",
        metadata: Mapping[str, Any] | None = None,
    ) -> dict[str, Any]:
        """Create a SmartBlock.

        Returns ``{"data": {"id": "uuid", "hash": "sha256:...", ...}}``.
        """
        body: dict[str, Any] = {
            "payload": dict(payload),
            "domain": domain,
            "metadata": dict(metadata) if metadata else {"source": "sbn-sdk"},
        }
        return self._t.post("/api/blocks", json=body).json()

    def submit(
        self,
        *,
        slot_id: str,
        payload: Mapping[str, Any],
        domain: str = "default",
        metadata: Mapping[str, Any] | None = None,
    ) -> dict[str, Any]:
        """Submit a client-supplied payload to an existing open slot.

        Runs through the full SmartBlock creation pipeline
        (factory → metrics → cDNA mutation → sign → snapchore) and persists
        the block with a foreign-key link back to the slot.

        Returns ``{"id": "uuid", "slot_id": "uuid", "hash": "sha256:...", ...}``.
        """
        body: dict[str, Any] = {
            "slot_id": slot_id,
            "payload": dict(payload),
            "domain": domain,
        }
        if metadata is not None:
            body["metadata"] = dict(metadata)
        data = self._t.post("/api/blocks/submit", json=body).json()
        return data.get("data") or data

    def get(self, block_id: str) -> dict[str, Any]:
        """Retrieve a SmartBlock by ID."""
        return self._t.get(f"/api/blocks/{block_id}").json()

    def get_bitblocks(
        self,
        block_id: str,
        *,
        include_stack: bool = False,
    ) -> dict[str, Any]:
        """Decompose a persisted SmartBlock into its constituent BitBlocks.

        Each SmartBlock payload is broken into Action, Interaction, Events,
        and Summary BitBlocks.  Optionally includes a composite Stack
        BitBlock that wraps all children.

        Returns ``{"block_id": "...", "slot_id": "...", "bitblocks": [...], "count": N}``.
        """
        params: dict[str, str] = {}
        if include_stack:
            params["include_stack"] = "true"
        data = self._t.get(f"/api/blocks/{block_id}/bitblocks", params=params).json()
        return data.get("data") or data

    def list(
        self,
        *,
        domain: str | None = None,
        limit: int = 50,
    ) -> list[dict[str, Any]]:
        params: dict[str, Any] = {"limit": limit}
        if domain:
            params["domain"] = domain
        data = self._t.get("/api/blocks", params=params).json()
        return data.get("data", {}).get("blocks", data.get("blocks", []))
