"""Agent SDK — lightweight client for autonomous agents on the SmartBlock Network.

The AgentClient exposes only the sub-clients an agent needs:

* ``gateway``   — create/close slots, fetch receipts, submit attestations
* ``snapchore`` — capture, verify, seal, chain management

For full platform access (blocks, governance, reality, lattice, GEC,
console management), use :class:`SbnClient` instead.

Usage::

    from sbn import AgentClient

    agent = AgentClient(base_url="https://api.smartblocks.network")
    agent.authenticate_api_key("sbn_live_abc123")

    # Open a computation slot
    slot = agent.gateway.create_slot(worker_id="agent-1", task_type="classify")

    # Hash the work product
    snap = agent.snapchore.capture({"result": "positive", "confidence": 0.97})

    # Submit attestation and close
    receipt = agent.gateway.request_attestation(summary)
    closure = agent.gateway.close_slot(slot.id)
"""

from __future__ import annotations

from typing import Sequence

from sbn._http import AuthState, HttpTransport, RetryConfig
from sbn.auth import MintedToken, SigningKey
from sbn.gateway import GatewayClient
from sbn.snapchore import SnapChoreClient


class AgentClient:
    """Lightweight client for autonomous agents on the SmartBlock Network.

    Exposes only ``gateway`` (slots, receipts, attestations) and
    ``snapchore`` (capture, verify, seal, chain) — the minimal surface
    an agent needs to participate in the network.

    For full platform access, use :class:`SbnClient`.
    """

    def __init__(
        self,
        *,
        base_url: str = "http://localhost:8090",
        tenant_id: str | None = None,
        retry: RetryConfig | None = None,
        timeout: float = 10.0,
        user_agent: str = "sbn-agent/0.3",
    ) -> None:
        self._auth = AuthState(tenant_id=tenant_id)
        self._transport = HttpTransport(
            base_url=base_url,
            auth=self._auth,
            retry=retry,
            timeout=timeout,
            user_agent=user_agent,
        )
        self._gateway = GatewayClient(self._transport)
        self._snapchore = SnapChoreClient(self._transport)

    # ── Auth methods ───────────────────────────────────────────────────

    def authenticate_api_key(self, api_key: str) -> None:
        """Set API key auth for all subsequent requests."""
        self._auth.api_key = api_key
        self._auth.bearer_token = None
        self._auth.token_provider = None

    def authenticate_bearer(self, token: str) -> None:
        """Set a static bearer token for all subsequent requests."""
        self._auth.bearer_token = token
        self._auth.api_key = None
        self._auth.token_provider = None

    def authenticate_signing_key(
        self,
        signing_key: SigningKey,
        *,
        subject: str = "sbn-agent",
        scopes: Sequence[str] = ("attest.write",),
        cdna: str = "agent",
        ttl_seconds: int = 300,
    ) -> None:
        """Use an Ed25519 signing key with auto-refreshing JWT tokens.

        This is the recommended auth method for long-running agents.
        """
        self._auth.api_key = None
        self._auth.bearer_token = None

        cache: dict[str, MintedToken] = {}

        def _provider() -> str:
            cached = cache.get("t")
            if cached and not cached.expired:
                return cached.token
            fresh = signing_key.issue_token(
                subject=subject,
                scopes=scopes,
                cdna=cdna,
                ttl_seconds=ttl_seconds,
                tenant_id=self._auth.tenant_id,
            )
            cache["t"] = fresh
            return fresh.token

        self._auth.token_provider = _provider

    def set_tenant(self, tenant_id: str | None) -> None:
        """Switch tenant context for multi-tenant operations."""
        self._auth.tenant_id = tenant_id

    # ── Sub-clients ────────────────────────────────────────────────────

    @property
    def gateway(self) -> GatewayClient:
        """Slot lifecycle, receipts, and attestations."""
        return self._gateway

    @property
    def snapchore(self) -> SnapChoreClient:
        """Capture, verify, seal, and chain management."""
        return self._snapchore

    # ── Lifecycle ──────────────────────────────────────────────────────

    def close(self) -> None:
        self._transport.close()

    def __enter__(self) -> AgentClient:
        return self

    def __exit__(self, exc_type, exc, tb) -> None:
        self.close()
