"""
aiel_sdk.integrations.openai.types
==================================

Stable datatypes for the AIEL OpenAI SDK surface.
"""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any, Dict, List, Optional, Tuple

Json = Dict[str, Any]


@dataclass(frozen=True)
class OpenAIResponsesCreateRequest:
    """Request payload for ``openai.responses.create``."""

    input: Any
    model: Optional[str] = None
    instructions: Optional[str] = None
    temperature: Optional[float] = None
    max_output_tokens: Optional[int] = None
    extra: Json = field(default_factory=dict)

    def validate(self) -> None:
        if self.input is None:
            raise ValueError("OpenAIResponsesCreateRequest.input is required")
        if self.max_output_tokens is not None and self.max_output_tokens <= 0:
            raise ValueError("OpenAIResponsesCreateRequest.max_output_tokens must be > 0")

    def to_params(self) -> Json:
        self.validate()
        out: Json = {"input": self.input}
        if (self.model or "").strip():
            out["model"] = self.model
        if (self.instructions or "").strip():
            out["instructions"] = self.instructions
        if self.temperature is not None:
            out["temperature"] = self.temperature
        if self.max_output_tokens is not None:
            out["max_output_tokens"] = self.max_output_tokens
        out.update(dict(self.extra or {}))
        return out


@dataclass(frozen=True)
class OpenAIResponsesCreateJsonRequest:
    """Request payload for ``openai.responses.create_json``."""

    input: Any
    model: Optional[str] = None
    json_schema: Optional[Json] = None
    instructions: Optional[str] = None
    temperature: Optional[float] = None
    max_output_tokens: Optional[int] = None
    extra: Json = field(default_factory=dict)

    def validate(self) -> None:
        if self.input is None:
            raise ValueError("OpenAIResponsesCreateJsonRequest.input is required")
        if self.max_output_tokens is not None and self.max_output_tokens <= 0:
            raise ValueError("OpenAIResponsesCreateJsonRequest.max_output_tokens must be > 0")
        if self.json_schema is not None and not isinstance(self.json_schema, dict):
            raise ValueError("OpenAIResponsesCreateJsonRequest.json_schema must be a dict")

    def to_params(self) -> Json:
        self.validate()
        out: Json = {"input": self.input}
        if (self.model or "").strip():
            out["model"] = self.model
        if self.json_schema is not None:
            out["json_schema"] = dict(self.json_schema)
        if (self.instructions or "").strip():
            out["instructions"] = self.instructions
        if self.temperature is not None:
            out["temperature"] = self.temperature
        if self.max_output_tokens is not None:
            out["max_output_tokens"] = self.max_output_tokens
        out.update(dict(self.extra or {}))
        return out


@dataclass(frozen=True)
class OpenAIEmbeddingsCreateRequest:
    """Request payload for ``openai.embeddings.create``."""

    input: Any
    model: Optional[str] = None
    dimensions: Optional[int] = None
    encoding_format: Optional[str] = None
    user: Optional[str] = None
    extra: Json = field(default_factory=dict)

    def validate(self) -> None:
        if self.input is None:
            raise ValueError("OpenAIEmbeddingsCreateRequest.input is required")
        if self.dimensions is not None and self.dimensions <= 0:
            raise ValueError("OpenAIEmbeddingsCreateRequest.dimensions must be > 0")

    def to_params(self) -> Json:
        self.validate()
        out: Json = {"input": self.input}
        if (self.model or "").strip():
            out["model"] = self.model
        if self.dimensions is not None:
            out["dimensions"] = self.dimensions
        if (self.encoding_format or "").strip():
            out["encoding_format"] = self.encoding_format
        if (self.user or "").strip():
            out["user"] = self.user
        out.update(dict(self.extra or {}))
        return out


@dataclass(frozen=True)
class OpenAIChatCompletionsCreateRequest:
    """Request payload for ``openai.chat.completions.create``."""

    messages: List[Json]
    model: Optional[str] = None
    temperature: Optional[float] = None
    max_tokens: Optional[int] = None
    tools: Optional[List[Json]] = None
    response_format: Optional[Json] = None
    extra: Json = field(default_factory=dict)

    def validate(self) -> None:
        if not isinstance(self.messages, list) or not self.messages:
            raise ValueError("OpenAIChatCompletionsCreateRequest.messages must be a non-empty list")
        if self.max_tokens is not None and self.max_tokens <= 0:
            raise ValueError("OpenAIChatCompletionsCreateRequest.max_tokens must be > 0")

    def to_params(self) -> Json:
        self.validate()
        out: Json = {"messages": list(self.messages)}
        if (self.model or "").strip():
            out["model"] = self.model
        if self.temperature is not None:
            out["temperature"] = self.temperature
        if self.max_tokens is not None:
            out["max_tokens"] = self.max_tokens
        if self.tools is not None:
            out["tools"] = list(self.tools)
        if self.response_format is not None:
            out["response_format"] = dict(self.response_format)
        out.update(dict(self.extra or {}))
        return out


@dataclass(frozen=True)
class OpenAIActionResult:
    raw: Json = field(default_factory=dict)

    @staticmethod
    def from_json(payload: Json) -> "OpenAIActionResult":
        return OpenAIActionResult(raw=dict(payload or {}))


@dataclass(frozen=True)
class OpenAIPingResult:
    ok: bool = False
    raw: Json = field(default_factory=dict)

    @staticmethod
    def from_json(payload: Json) -> "OpenAIPingResult":
        return OpenAIPingResult(ok=bool(payload.get("ok", False)), raw=dict(payload or {}))


@dataclass(frozen=True)
class OpenAICapability:
    id: str
    label: str
    description: str
    group: str
    group_label: str
    action: str


@dataclass(frozen=True)
class OpenAICapabilities:
    items: Tuple[OpenAICapability, ...]

    def ids(self) -> List[str]:
        return [c.id for c in self.items]

    def actions(self) -> List[str]:
        return [c.action for c in self.items]


DEFAULT_OPENAI_CAPABILITIES = OpenAICapabilities(
    items=(
        OpenAICapability(
            id="openai:responses:create",
            label="Responses Create",
            description="Create an OpenAI responses output.",
            group="Generation",
            group_label="OpenAI integration",
            action="openai.responses.create",
        ),
        OpenAICapability(
            id="openai:responses:create_json",
            label="Responses Create JSON",
            description="Create structured JSON output via OpenAI responses.",
            group="Generation",
            group_label="OpenAI integration",
            action="openai.responses.create_json",
        ),
        OpenAICapability(
            id="openai:embeddings:create",
            label="Embeddings Create",
            description="Create text embeddings with OpenAI.",
            group="Embeddings",
            group_label="OpenAI integration",
            action="openai.embeddings.create",
        ),
        OpenAICapability(
            id="openai:chat:completions:create",
            label="Chat Completions Create",
            description="Create chat completions with OpenAI.",
            group="Generation",
            group_label="OpenAI integration",
            action="openai.chat.completions.create",
        ),
        OpenAICapability(
            id="openai:ping",
            label="Ping",
            description="Check OpenAI connectivity.",
            group="Health",
            group_label="OpenAI integration",
            action="openai.ping",
        ),
    )
)
