from __future__ import annotations

import json
from urllib.error import HTTPError, URLError
from urllib.parse import urljoin
from urllib.request import Request, urlopen


class WorkspaceTrustApiClient:
    """Passive API client for one-time pairing and workspace trust heartbeat."""

    def __init__(self, base_url: str) -> None:
        self.base_url = base_url

    def _post_json(self, path: str, body: dict[str, object], headers: dict[str, str] | None = None) -> dict[str, object]:
        url = urljoin(self.base_url.rstrip("/") + "/", path.lstrip("/"))
        payload = json.dumps(body, ensure_ascii=True, separators=(",", ":")).encode("utf-8")
        request_headers = {"Content-Type": "application/json"}
        if headers:
            request_headers.update(headers)

        request = Request(url=url, data=payload, headers=request_headers, method="POST")
        try:
            with urlopen(request, timeout=15) as response:
                raw = response.read().decode("utf-8")
                return json.loads(raw) if raw else {}
        except HTTPError as exc:
            raw = exc.read().decode("utf-8", errors="replace")
            detail = "backend_http_error"
            try:
                parsed = json.loads(raw)
                detail = str(parsed.get("detail", detail))
            except Exception:
                detail = "backend_http_error"
            raise RuntimeError(f"http_{exc.code}:{detail}") from exc
        except URLError as exc:
            raise RuntimeError("backend_unreachable") from exc

    def authenticate_pair_token(self, pair_token: str) -> dict[str, object]:
        return self._post_json(
            "/api/devices/pair-token/authenticate",
            {"token": pair_token},
        )

    def pair_workspace(self, *, auth_token: str, payload: dict[str, object]) -> dict[str, object]:
        return self._post_json(
            "/api/connect/workspace/pair",
            payload,
            headers={"Authorization": f"Bearer {auth_token}"},
        )

    def send_workspace_heartbeat(self, *, auth_token: str, payload: dict[str, object]) -> dict[str, object]:
        return self._post_json(
            "/api/connect/workspace/heartbeat",
            payload,
            headers={"Authorization": f"Bearer {auth_token}"},
        )

    def revoke_workspace(self, *, auth_token: str, project_identity_uuid: str, reason_code: str = "manual_revoke") -> dict[str, object]:
        return self._post_json(
            "/api/connect/workspace/revoke",
            {"project_identity_uuid": project_identity_uuid, "reason_code": reason_code},
            headers={"Authorization": f"Bearer {auth_token}"},
        )
