"""Governance sub-client — proposal lifecycle: submit, approve, reject, promote."""

from __future__ import annotations

from typing import Any, Mapping

from sbn._http import HttpTransport

PREFIX = "/api/governance"


class GovernanceClient:
    """Governance proposal lifecycle management.

    Provides SDK access to the SBN governance pipeline for submitting,
    approving, rejecting, and promoting sealed proposals. Each proposal
    flows through a multi-approver quorum before it can be promoted to
    production.

    Example::

        client = SbnClient(base_url="https://api.smartblocks.network")
        client.authenticate_api_key("sbn_live_...")

        # Submit a new governance proposal
        proposal = client.governance.create_proposal({
            "document": {
                "frontier_id": "core-ops",
                "submitter": "mycal",
                "risk_band": "low",
                "description": "Increase c_max from 1.0 to 1.2",
            },
            "metrics": {"gec_summary": {"frontier_id": "core-ops"}},
        })

        # Approve it
        client.governance.approve(
            proposal["id"],
            approver="alice",
            note="LGTM",
        )
    """

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

    # ── Proposal CRUD ──────────────────────────────────────────────────

    def create_proposal(
        self,
        proposal: Mapping[str, Any],
    ) -> dict[str, Any]:
        """Submit a sealed governance proposal.

        Parameters
        ----------
        proposal : dict
            The proposal payload. Should contain at minimum a ``"document"``
            key with the proposal body. Optional keys: ``"metrics"``,
            ``"snapchore_hash"``.

        Returns
        -------
        dict
            ``{"id": "...", "status": "pending", "checksum": "..."}``.
        """
        return self._t.post(
            f"{PREFIX}/proposals", json={"proposal": dict(proposal)}
        ).json()

    def list_proposals(
        self,
        *,
        status: str | None = None,
        frontier: str | None = None,
    ) -> dict[str, Any]:
        """List proposals for the current project.

        Parameters
        ----------
        status : str, optional
            Filter by status (``"pending"``, ``"approved"``, ``"rejected"``,
            ``"promoted"``).
        frontier : str, optional
            Filter by frontier ID.

        Returns
        -------
        dict
            ``{"proposals": [...]}``.
        """
        params: dict[str, str] = {}
        if status:
            params["status_filter"] = status
        if frontier:
            params["frontier"] = frontier
        return self._t.get(f"{PREFIX}/proposals", params=params).json()

    def get_proposal(self, proposal_id: str) -> dict[str, Any]:
        """Get a proposal with its full approval history.

        Returns the proposal document, metadata, and all recorded
        approvals/rejections.
        """
        return self._t.get(f"{PREFIX}/proposals/{proposal_id}").json()

    # ── Approval lifecycle ─────────────────────────────────────────────

    def approve(
        self,
        proposal_id: str,
        *,
        approver: str,
        signature: str | None = None,
        note: str | None = None,
    ) -> dict[str, Any]:
        """Record an approval on a proposal.

        When ``approvals_received >= approvals_required`` the proposal status
        automatically transitions to ``"approved"``.

        Returns
        -------
        dict
            ``{"id": "...", "status": "...", "approvals_received": ...,
            "approvals_required": ...}``.
        """
        body: dict[str, Any] = {"approver": approver}
        if signature is not None:
            body["signature"] = signature
        if note is not None:
            body["note"] = note
        return self._t.post(
            f"{PREFIX}/proposals/{proposal_id}/approve", json=body
        ).json()

    def reject(
        self,
        proposal_id: str,
        *,
        approver: str,
        signature: str | None = None,
        note: str | None = None,
    ) -> dict[str, Any]:
        """Record a rejection on a proposal.

        Immediately sets the proposal status to ``"rejected"``.

        Returns
        -------
        dict
            ``{"id": "...", "status": "rejected"}``.
        """
        body: dict[str, Any] = {"approver": approver}
        if signature is not None:
            body["signature"] = signature
        if note is not None:
            body["note"] = note
        return self._t.post(
            f"{PREFIX}/proposals/{proposal_id}/reject", json=body
        ).json()

    def promote(self, proposal_id: str) -> dict[str, Any]:
        """Promote an approved proposal to production.

        Only works on proposals with status ``"approved"``.

        Returns
        -------
        dict
            ``{"id": "...", "status": "promoted"}``.
        """
        return self._t.post(
            f"{PREFIX}/proposals/{proposal_id}/promote", json={}
        ).json()
