"""
clawtrak-gateway — Python SDK for the Claw Agent Gateway

Usage:
    from clawtrak_gateway import ClawGateway

    gw = ClawGateway(token="claw_...")
    page = gw.read("pixelfamiliar.ca", "/")
    md = gw.markdown("pixelfamiliar.ca", "/about")
    actions = gw.actions("pixelfamiliar.ca")
"""

import json
from dataclasses import dataclass, field
from typing import Any, Optional
from urllib.request import Request, urlopen
from urllib.error import URLError

DEFAULT_BASE_URL = "https://claw-edge-router.clawgateway.workers.dev"


@dataclass
class GatewayResponse:
    """Response from the Claw Agent Gateway."""
    status: int
    headers: dict
    body: str
    verified: bool = False
    proxy_mode: Optional[str] = None


@dataclass
class ActionSchema:
    """An action contract discovered from a domain."""
    action_name: str
    description: str
    endpoint_path: str
    http_method: str
    payload_schema: dict = field(default_factory=dict)


class ClawGateway:
    """Client for the Claw Agent Gateway edge router."""

    def __init__(
        self,
        token: str,
        base_url: str = DEFAULT_BASE_URL,
        timeout: int = 30,
    ):
        if not token:
            raise ValueError("ClawGateway: token is required")
        self.token = token
        self.base_url = base_url.rstrip("/")
        self.timeout = timeout

    def read(self, domain: str, path: str = "/") -> GatewayResponse:
        """Read a page through the gateway (HTML passthrough)."""
        return self._request(domain, path, {"Accept": "text/html"})

    def markdown(self, domain: str, path: str = "/") -> GatewayResponse:
        """Get a page as clean Markdown (ClawProxy)."""
        return self._request(domain, path, {"Accept": "text/markdown"})

    def actions(self, domain: str) -> list[ActionSchema]:
        """Discover action contracts for a domain."""
        res = self._request(
            domain,
            "/.well-known/agent-actions.json",
            {"Accept": "application/json"},
        )
        try:
            data = json.loads(res.body)
            return [ActionSchema(**a) for a in data.get("actions", [])]
        except (json.JSONDecodeError, TypeError):
            return []

    def execute(
        self,
        domain: str,
        action_name: str,
        payload: Optional[dict] = None,
    ) -> GatewayResponse:
        """Execute an action contract by name."""
        all_actions = self.actions(domain)
        action = next((a for a in all_actions if a.action_name == action_name), None)
        if not action:
            raise ValueError(f'Action "{action_name}" not found on {domain}')

        url = f"{self.base_url}{action.endpoint_path}"
        headers = {
            "X-Claw-Agent-Token": self.token,
            "X-Claw-Target": domain,
            "Content-Type": "application/json",
        }
        body = json.dumps(payload).encode() if payload else None
        req = Request(url, data=body, headers=headers, method=action.http_method)
        return self._do_request(req)

    def health(self) -> dict:
        """Check edge router health."""
        req = Request(f"{self.base_url}/__claw/health")
        with urlopen(req, timeout=self.timeout) as res:
            return json.loads(res.read().decode())

    def info(self) -> dict:
        """Get gateway capabilities and protocol info."""
        req = Request(f"{self.base_url}/__claw/info")
        with urlopen(req, timeout=self.timeout) as res:
            return json.loads(res.read().decode())

    def _request(
        self,
        domain: str,
        path: str,
        extra_headers: Optional[dict] = None,
    ) -> GatewayResponse:
        url = f"{self.base_url}{path}"
        headers = {
            "X-Claw-Agent-Token": self.token,
            "X-Claw-Target": domain,
        }
        if extra_headers:
            headers.update(extra_headers)

        req = Request(url, headers=headers)
        return self._do_request(req)

    def _do_request(self, req: Request) -> GatewayResponse:
        try:
            with urlopen(req, timeout=self.timeout) as res:
                body = res.read().decode("utf-8", errors="replace")
                headers = dict(res.getheaders())
                return GatewayResponse(
                    status=res.status,
                    headers=headers,
                    body=body,
                    verified=headers.get("x-agent-verified") == "true",
                    proxy_mode=headers.get("x-clawproxy"),
                )
        except URLError as e:
            raise ConnectionError(f"Gateway request failed: {e}") from e
