# https://chatgpt.com/g/g-p-6923b2ccf7588191beff26d5f860fc1e-ai-execution-layer/c/697e441a-1f78-8332-883f-ce1743f8a9d1
from __future__ import annotations

import json
import urllib.error
import urllib.request
from typing import Any, Dict, List, Optional

from pydantic import BaseModel, ConfigDict, Field

from aiel_sdk.errors import AielError


class IntegrationApiError(AielError):
    def __init__(self, status: int, message: str, body: Any | None = None):
        details = f"Integration API error ({status}): {message}"
        if body is not None:
            details += f" | body={body}"
        super().__init__(details)
        self.status = status
        self.body = body


class IntegrationConnector(BaseModel):
    model_config = ConfigDict(extra="allow")

    id: str
    version: str


class IntegrationAuth(BaseModel):
    model_config = ConfigDict(extra="allow")

    method: str
    resource_credential_id: Optional[str] = None
    oauth_client_profile_id: Optional[str] = None


class IntegrationConnection(BaseModel):
    model_config = ConfigDict(extra="allow")

    connection_id: str
    workspace_id: str
    project_id: str
    provider: str
    connector: IntegrationConnector
    resource_type: str
    display_name: str
    status: str
    status_reason: Optional[str] = None
    capabilities: List[str] = Field(default_factory=list)
    allowed_actions: List[str] = Field(default_factory=list)
    granted_actions: List[str] = Field(default_factory=list)
    auth: IntegrationAuth
    metadata: Dict[str, Any] = Field(default_factory=dict)


class IntegrationsClient:
    def __init__(
        self,
        base_url: str,
        api_key: str | None = None,
        timeout: float = 30.0,
        extra_headers: Optional[Dict[str, str]] = None,
    ) -> None:
        """
        Client for backend integrations.

        Args:
            base_url: Base API URL (e.g., https://api.example.com).
            api_key: Bearer token for API auth, if required.
            timeout: Request timeout in seconds.
            extra_headers: Additional headers to send with each request.
        """
        self.base_url = base_url.rstrip("/")
        self.api_key = api_key
        self.timeout = timeout
        self.extra_headers = extra_headers or {}

        if not self.base_url:
            raise ValueError("base_url is required")

    def list(self, workspace_id: str, project_id: str) -> List[IntegrationConnection]:
        """List integration connections for a project."""
        path = f"/v1/workspaces/{workspace_id}/projects/{project_id}/integrations"
        data = self._request("GET", path)
        return [IntegrationConnection.model_validate(item) for item in data or []]

    def get(
        self,
        workspace_id: str,
        project_id: str,
        connection_id: str,
    ) -> IntegrationConnection:
        """Fetch a single integration connection by id."""
        path = f"/v1/workspaces/{workspace_id}/projects/{project_id}/integrations/{connection_id}"
        data = self._request("GET", path)
        return IntegrationConnection.model_validate(data)

    def invoke_action(
        self,
        workspace_id: str,
        project_id: str,
        connection_id: str,
        action: str,
        payload: Optional[Dict[str, Any]] = None,
    ) -> Dict[str, Any]:
        """Invoke an integration action with a provider-specific payload."""
        path = (
            f"/v1/workspaces/{workspace_id}/projects/{project_id}"
            f"/integrations/{connection_id}/actions/{action}"
        )
        data = self._request("POST", path, json_body=payload or {})
        return data or {}

    def _request(self, method: str, path: str, json_body: Any | None = None) -> Any:
        """Low-level HTTP helper used by public methods."""
        url = f"{self.base_url}/{path}"
        headers = {"Content-Type": "application/json", **self.extra_headers}
        if self.api_key:
            headers["X-API-Token"] = f"{self.api_key}"

        data = None
        if json_body is not None:
            data = json.dumps(json_body).encode("utf-8")

        req = urllib.request.Request(url, data=data, headers=headers, method=method)
        try:
            with urllib.request.urlopen(req, timeout=self.timeout) as resp:
                raw = resp.read()
                if not raw:
                    return None
                try:
                    return json.loads(raw.decode("utf-8"))
                except json.JSONDecodeError:
                    return raw.decode("utf-8")
        except urllib.error.HTTPError as e:
            body = None
            try:
                raw = e.read()
                if raw:
                    body = json.loads(raw.decode("utf-8"))
                else:
                    body = None
            except Exception:
                body = None
            raise IntegrationApiError(e.code, e.reason, body) from e


__all__ = [
    "IntegrationApiError",
    "IntegrationAuth",
    "IntegrationConnector",
    "IntegrationConnection",
    "IntegrationsClient",
]
