"""Async HTTP client for the Brehon Privacy API."""

import os
import re
from typing import Any

import httpx

_VALID_LAW_ID = re.compile(r"^[a-z0-9\-]+$")

_client: "BrehonAPIClient | None" = None


def get_client() -> "BrehonAPIClient":
    """Return a lazy singleton client instance."""
    global _client
    if _client is None:
        _client = BrehonAPIClient()
    return _client


class BrehonAPIClient:
    """Thin async wrapper around the Brehon Privacy REST API."""

    def __init__(self) -> None:
        self.api_key = os.environ.get("BREHON_API_KEY", "")
        self.base_url = os.environ.get(
            "BREHON_API_BASE_URL", "https://api.brehon.dev/api/v1"
        ).rstrip("/")
        self._http: httpx.AsyncClient | None = None

    def _get_http(self) -> httpx.AsyncClient:
        if self._http is None or self._http.is_closed:
            self._http = httpx.AsyncClient(
                base_url=self.base_url,
                headers={
                    "Authorization": f"Bearer {self.api_key}",
                    "User-Agent": "brehon-mcp-server/1.0.0",
                },
                timeout=30.0,
            )
        return self._http

    async def _request(
        self,
        method: str,
        path: str,
        *,
        params: dict[str, Any] | None = None,
        json: Any = None,
    ) -> dict[str, Any] | list[Any]:
        """Central request method. Never raises — returns error dicts on failure."""
        if not self.api_key:
            return {
                "error": True,
                "detail": "BREHON_API_KEY environment variable is not set. "
                "Get a free key at https://brehon.dev",
            }
        try:
            resp = await self._get_http().request(
                method, path, params=params, json=json
            )
            data = resp.json()
            if resp.is_error:
                return {
                    "error": True,
                    "status_code": resp.status_code,
                    "detail": data.get("detail", f"HTTP {resp.status_code}"),
                }
            return data
        except httpx.HTTPError as exc:
            return {"error": True, "detail": f"Request failed: {exc}"}
        except Exception as exc:
            return {"error": True, "detail": f"Unexpected error: {exc}"}

    # ── Privacy Laws ─────────────────────────────────────────────

    async def search_privacy_laws(
        self,
        law_type: str | None = None,
        jurisdiction: str | None = None,
        geographic_scope: str | None = None,
        sub_type: str | None = None,
    ) -> dict[str, Any] | list[Any]:
        params: dict[str, str] = {}
        if law_type:
            params["law_type"] = law_type
        if jurisdiction:
            params["jurisdiction"] = jurisdiction
        if geographic_scope:
            params["geographic_scope"] = geographic_scope
        if sub_type:
            params["sub_type"] = sub_type
        return await self._request("GET", "/privacy-laws", params=params or None)

    @staticmethod
    def _validate_law_id(law_id: str) -> str | None:
        """Return an error message if law_id contains invalid characters."""
        if not _VALID_LAW_ID.match(law_id):
            return f"Invalid law_id '{law_id}'. Must contain only lowercase letters, digits, and hyphens."
        return None

    async def get_privacy_law_details(self, law_id: str) -> dict[str, Any] | list[Any]:
        if err := self._validate_law_id(law_id):
            return {"error": True, "detail": err}
        return await self._request("GET", f"/privacy-laws/{law_id}")

    async def get_data_subject_rights(self, law_id: str) -> dict[str, Any] | list[Any]:
        if err := self._validate_law_id(law_id):
            return {"error": True, "detail": err}
        return await self._request("GET", f"/privacy-laws/{law_id}/rights")

    async def get_legal_bases(self, law_id: str) -> dict[str, Any] | list[Any]:
        if err := self._validate_law_id(law_id):
            return {"error": True, "detail": err}
        return await self._request("GET", f"/privacy-laws/{law_id}/legal-bases")

    async def get_penalties(self, law_id: str) -> dict[str, Any] | list[Any]:
        if err := self._validate_law_id(law_id):
            return {"error": True, "detail": err}
        return await self._request("GET", f"/privacy-laws/{law_id}/penalties")

    async def get_principles(self, law_id: str) -> dict[str, Any] | list[Any]:
        if err := self._validate_law_id(law_id):
            return {"error": True, "detail": err}
        return await self._request("GET", f"/privacy-laws/{law_id}/principles")

    async def get_exemptions(self, law_id: str) -> dict[str, Any] | list[Any]:
        if err := self._validate_law_id(law_id):
            return {"error": True, "detail": err}
        return await self._request("GET", f"/privacy-laws/{law_id}/exemptions")

    async def compare_privacy_laws(
        self, law_ids: list[str]
    ) -> dict[str, Any] | list[Any]:
        return await self._request("POST", "/privacy-laws/compare", json=law_ids)

    async def search_law_content(
        self, q: str, fields: str | None = None
    ) -> dict[str, Any] | list[Any]:
        params: dict[str, str] = {"q": q}
        if fields:
            params["fields"] = fields
        return await self._request("GET", "/privacy-laws/search", params=params)

    async def get_applicable_laws(
        self, jurisdictions: list[str]
    ) -> dict[str, Any] | list[Any]:
        return await self._request(
            "POST",
            "/privacy-laws/applicable",
            json={"jurisdictions": jurisdictions},
        )

    # ── Utility ──────────────────────────────────────────────────

    async def get_jurisdictions(self) -> dict[str, Any] | list[Any]:
        return await self._request("GET", "/jurisdictions")

    async def get_all_laws_summary(self) -> dict[str, Any] | list[Any]:
        return await self._request("GET", "/privacy-laws")
