"""Authenticated, non-mutating Supraworx device-readiness verification."""

from __future__ import annotations

from typing import Any, Mapping, Optional

from .http import TransportError, UrllibTransport


READINESS_SCHEMA = "labcobot.device-readiness.v1"


class DeviceReadinessError(RuntimeError):
    """The remote registry could not prove the configured device identity."""


class DeviceReadinessClient:
    """Verify registration and feature provisioning without creating records."""

    def __init__(
        self,
        *,
        readiness_url: str,
        uid_device: str,
        api_secret: str,
        manufacturer_id: str = "",
        transport: Optional[UrllibTransport] = None,
        timeout: float = 15.0,
        allow_insecure_http: bool = False,
    ) -> None:
        if not readiness_url:
            raise ValueError("Device readiness URL is required")
        if (
            not allow_insecure_http
            and not readiness_url.lower().startswith("https://")
        ):
            raise ValueError("Device readiness URL must use HTTPS")
        if not uid_device or not api_secret:
            raise ValueError("Device readiness requires UID and API secret")
        self.readiness_url = str(readiness_url)
        self.uid_device = str(uid_device)
        self.api_secret = str(api_secret)
        self.manufacturer_id = str(manufacturer_id)
        self.transport = transport or UrllibTransport()
        self.timeout = float(timeout)

    def verify(self) -> Mapping[str, Any]:
        """Return a bounded, secret-free readiness document."""

        try:
            response = self.transport.request(
                "GET",
                self.readiness_url,
                headers={
                    "Accept": "application/json",
                    "Cache-Control": "no-cache",
                    "User-Agent": "LabCobot-Readiness/1",
                    "X-Device-Id": self.uid_device,
                    "X-Device-Secret": self.api_secret,
                },
                timeout=self.timeout,
                max_response_bytes=256 * 1024,
            )
        except TransportError as exc:
            raise DeviceReadinessError(
                "Supraworx device registry is unavailable"
            ) from exc
        if not 200 <= response.status_code < 300:
            raise DeviceReadinessError(
                "Supraworx readiness returned HTTP {}".format(
                    response.status_code
                )
            )
        try:
            payload = response.json()
        except TransportError as exc:
            raise DeviceReadinessError(
                "Supraworx readiness returned invalid JSON"
            ) from exc
        if not isinstance(payload, Mapping):
            raise DeviceReadinessError(
                "Supraworx readiness response must be an object"
            )
        if payload.get("schema_version") != READINESS_SCHEMA:
            raise DeviceReadinessError(
                "Supraworx readiness schema is unsupported"
            )
        device = payload.get("device")
        features = payload.get("features")
        if not isinstance(device, Mapping) or not isinstance(features, Mapping):
            raise DeviceReadinessError(
                "Supraworx readiness response is incomplete"
            )
        if str(device.get("uid_device") or "") != self.uid_device:
            raise DeviceReadinessError(
                "Supraworx readiness returned another device"
            )
        if device.get("registered") is not True:
            raise DeviceReadinessError(
                "Supraworx did not confirm device registration"
            )
        if (
            self.manufacturer_id
            and str(device.get("manufacturer_id") or "")
            != self.manufacturer_id
        ):
            raise DeviceReadinessError(
                "Supraworx manufacturer identity does not match"
            )
        return {
            "schema_version": READINESS_SCHEMA,
            "verified": True,
            "device": {
                "uid_device": self.uid_device,
                "manufacturer_id": str(device.get("manufacturer_id") or ""),
                "device_type": str(device.get("device_type") or ""),
                "software_version": str(device.get("software_version") or ""),
                "registered": True,
            },
            "features": dict(features),
            "server_time": str(payload.get("server_time") or ""),
        }


__all__ = [
    "DeviceReadinessClient",
    "DeviceReadinessError",
    "READINESS_SCHEMA",
]
