"""Obol API client - HTTP communication with Obol cloud."""
import json
from typing import Optional

import urllib.request
import urllib.error


class ObolAPIError(Exception):
    def __init__(self, status_code: int, detail: str):
        self.status_code = status_code
        self.detail = detail
        super().__init__(f"Obol API error {status_code}: {detail}")


class ObolAPI:
    """Low-level HTTP client for Obol API. Zero external dependencies."""

    def __init__(self, api_key: str, base_url: str):
        self.api_key = api_key
        self.base_url = base_url.rstrip("/")

    def _request(self, method: str, path: str, data: dict = None) -> dict:
        url = f"{self.base_url}{path}"
        headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json",
            "User-Agent": "obol-sdk/0.1.0",
        }

        body = json.dumps(data).encode() if data else None
        req = urllib.request.Request(url, data=body, headers=headers, method=method)

        try:
            with urllib.request.urlopen(req, timeout=10) as resp:
                return json.loads(resp.read().decode())
        except urllib.error.HTTPError as e:
            try:
                detail = json.loads(e.read().decode()).get("detail", str(e))
            except Exception:
                detail = str(e)
            raise ObolAPIError(e.code, detail)

    def register_agent(self, name: str, platform: str = None, model: str = None,
                       framework: str = None, capabilities: list = None,
                       metadata: dict = None) -> dict:
        payload = {
            "name": name,
            "capabilities": capabilities or [],
            "metadata": metadata or {},
        }
        if platform:
            payload["platform"] = platform
        if model:
            payload["model"] = model
        if framework:
            payload["framework"] = framework
        return self._request("POST", "/agents", payload)

    def list_agents(self) -> dict:
        return self._request("GET", "/agents")

    def get_agent(self, agent_id: int) -> dict:
        return self._request("GET", f"/agents/{agent_id}")

    def record_event(self, agent_id: int, session_id: str, action: str,
                     target: str = None, result: str = "success",
                     duration_ms: int = None, target_hash: str = None,
                     content_size: int = None, content_type: str = None,
                     detected_patterns: list = None, metadata: dict = None) -> dict:
        return self._request("POST", "/events", {
            "agent_id": agent_id,
            "session_id": session_id,
            "action": action,
            "target": target,
            "target_hash": target_hash,
            "content_size": content_size,
            "content_type": content_type,
            "result": result,
            "duration_ms": duration_ms,
            "detected_patterns": detected_patterns or [],
            "metadata": metadata or {},
        })

    def record_events_batch(self, events: list[dict]) -> dict:
        return self._request("POST", "/events/batch", {"events": events})

    def get_score(self, agent_id: int) -> dict:
        return self._request("GET", f"/agents/{agent_id}/score")

    def get_events(self, agent_id: int, limit: int = 50, offset: int = 0) -> dict:
        return self._request("GET", f"/agents/{agent_id}/events?limit={limit}&offset={offset}")

    def check_access(self, agent_id: int, action: str, resource: str) -> dict:
        return self._request("POST", "/access/check", {
            "agent_id": agent_id,
            "action": action,
            "resource": resource,
        })

    def create_policy(self, resource: str, min_trust: float = 50,
                      min_tier: str = "trusted", action: str = "block") -> dict:
        return self._request("POST", "/policies", {
            "resource": resource,
            "min_trust": min_trust,
            "min_tier": min_tier,
            "action": action,
        })

    def list_policies(self) -> dict:
        return self._request("GET", "/policies")

    # --- Compliance ---

    def get_compliance_status(self) -> dict:
        return self._request("GET", "/compliance/status")

    def get_compliance_status_detail(self, slug: str) -> dict:
        return self._request("GET", f"/compliance/status/{slug}")

    def get_compliance_report(self, slug: str = None) -> dict:
        path = f"/compliance/report/{slug}" if slug else "/compliance/report"
        return self._request("GET", path)

    def list_regulations(self) -> dict:
        return self._request("GET", "/compliance/regulations")

    def get_regulation(self, slug: str) -> dict:
        return self._request("GET", f"/compliance/regulations/{slug}")

    def set_compliance_profile(self, industry: str, jurisdictions: list[str]) -> dict:
        return self._request("POST", "/compliance/profile", {
            "industry": industry,
            "jurisdictions": jurisdictions,
        })

    def get_compliance_profile(self) -> dict:
        return self._request("GET", "/compliance/profile")

    def enable_regulation(self, slug: str) -> dict:
        return self._request("POST", f"/compliance/regulations/{slug}/enable")

    def disable_regulation(self, slug: str) -> dict:
        return self._request("POST", f"/compliance/regulations/{slug}/disable")

    def recompute_compliance(self) -> dict:
        return self._request("POST", "/compliance/recompute")

    # --- Dashboard ---

    def get_dashboard_summary(self) -> dict:
        return self._request("GET", "/dashboard/summary")

    # --- Alerts ---

    def list_alerts(self, status: str = None, severity: str = None,
                    agent_id: int = None, limit: int = 50) -> dict:
        params = []
        if status:
            params.append(f"status={status}")
        if severity:
            params.append(f"severity={severity}")
        if agent_id:
            params.append(f"agent_id={agent_id}")
        params.append(f"limit={limit}")
        qs = "&".join(params)
        return self._request("GET", f"/alerts?{qs}")

    def resolve_alert(self, alert_id: int, status: str = "resolved",
                      resolved_by: str = "cli") -> dict:
        return self._request("PATCH", f"/alerts/{alert_id}", {
            "status": status,
            "resolved_by": resolved_by,
        })

    # --- Events (search) ---

    def search_events(self, agent_id: int = None, action: str = None,
                      since: str = None, until: str = None,
                      session_id: str = None,
                      limit: int = 50, offset: int = 0) -> dict:
        params = [f"limit={limit}", f"offset={offset}"]
        if agent_id:
            params.append(f"agent_id={agent_id}")
        if action:
            params.append(f"action={action}")
        if since:
            params.append(f"since={since}")
        if until:
            params.append(f"until={until}")
        if session_id:
            params.append(f"session_id={session_id}")
        qs = "&".join(params)
        return self._request("GET", f"/events?{qs}")
