"""
aiel_sdk.integrations.firebase.types
====================================

Stable datatypes for the AIEL Firebase 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 FirebaseDocGetRequest:
    collection: str
    doc_id: str

    def validate(self) -> None:
        if not (self.collection or "").strip():
            raise ValueError("FirebaseDocGetRequest.collection must be non-empty")
        if not (self.doc_id or "").strip():
            raise ValueError("FirebaseDocGetRequest.doc_id must be non-empty")

    def to_params(self) -> Json:
        self.validate()
        return {"collection": self.collection, "doc_id": self.doc_id}


@dataclass(frozen=True)
class FirebaseDocPutRequest:
    collection: str
    doc_id: str
    data: Json
    merge: Optional[bool] = None
    idempotency_key: Optional[str] = None

    def validate(self) -> None:
        if not (self.collection or "").strip():
            raise ValueError("FirebaseDocPutRequest.collection must be non-empty")
        if not (self.doc_id or "").strip():
            raise ValueError("FirebaseDocPutRequest.doc_id must be non-empty")
        if not isinstance(self.data, dict) or not self.data:
            raise ValueError("FirebaseDocPutRequest.data must be a non-empty dict")

    def to_params(self) -> Json:
        self.validate()
        out: Json = {"collection": self.collection, "doc_id": self.doc_id, "data": dict(self.data)}
        if self.merge is not None:
            out["merge"] = bool(self.merge)
        if (self.idempotency_key or "").strip():
            out["idempotency_key"] = self.idempotency_key
        return out


@dataclass(frozen=True)
class FirebaseDocDeleteRequest:
    collection: str
    doc_id: str
    idempotency_key: Optional[str] = None

    def validate(self) -> None:
        if not (self.collection or "").strip():
            raise ValueError("FirebaseDocDeleteRequest.collection must be non-empty")
        if not (self.doc_id or "").strip():
            raise ValueError("FirebaseDocDeleteRequest.doc_id must be non-empty")

    def to_params(self) -> Json:
        self.validate()
        out: Json = {"collection": self.collection, "doc_id": self.doc_id}
        if (self.idempotency_key or "").strip():
            out["idempotency_key"] = self.idempotency_key
        return out


@dataclass(frozen=True)
class FirebaseDocQueryRequest:
    collection: str
    where: Optional[Any] = None
    order_by: Optional[Any] = None
    limit: Optional[int] = None
    collection_group: Optional[str] = None

    def validate(self) -> None:
        if not (self.collection or "").strip():
            raise ValueError("FirebaseDocQueryRequest.collection must be non-empty")
        if self.limit is not None and self.limit <= 0:
            raise ValueError("FirebaseDocQueryRequest.limit must be > 0 when provided")

    def to_params(self) -> Json:
        self.validate()
        out: Json = {"collection": self.collection}
        if self.where is not None:
            out["where"] = self.where
        if self.order_by is not None:
            out["order_by"] = self.order_by
        if self.limit is not None:
            out["limit"] = self.limit
        if (self.collection_group or "").strip():
            out["collection_group"] = self.collection_group
        return out


@dataclass(frozen=True)
class FirebaseDocResult:
    document: Optional[Json] = None
    found: Optional[bool] = None
    raw: Json = field(default_factory=dict)

    @staticmethod
    def from_json(payload: Json) -> "FirebaseDocResult":
        doc = payload.get("document")
        if not isinstance(doc, dict):
            doc = None
        return FirebaseDocResult(document=doc, found=payload.get("found"), raw=dict(payload or {}))


@dataclass(frozen=True)
class FirebaseDocQueryResult:
    documents: List[Json] = field(default_factory=list)
    count: Optional[int] = None
    raw: Json = field(default_factory=dict)

    @staticmethod
    def from_json(payload: Json) -> "FirebaseDocQueryResult":
        docs_raw = payload.get("documents")
        docs: List[Json] = []
        if isinstance(docs_raw, list):
            docs = [dict(x) for x in docs_raw if isinstance(x, dict)]
        return FirebaseDocQueryResult(documents=docs, count=payload.get("count"), raw=dict(payload or {}))


@dataclass(frozen=True)
class FirebaseDeleteResult:
    deleted: Optional[bool] = None
    raw: Json = field(default_factory=dict)

    @staticmethod
    def from_json(payload: Json) -> "FirebaseDeleteResult":
        return FirebaseDeleteResult(deleted=payload.get("deleted"), raw=dict(payload or {}))


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

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


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


@dataclass(frozen=True)
class FirebaseCapabilities:
    items: Tuple[FirebaseCapability, ...]

    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_FIREBASE_CAPABILITIES = FirebaseCapabilities(
    items=(
        FirebaseCapability(
            id="firebase:doc:get",
            label="Get Document",
            description="Read a single Firebase document by collection and document id.",
            group="Document",
            group_label="Firebase integration",
            action="firebase.doc.get",
        ),
        FirebaseCapability(
            id="firebase:doc:put",
            label="Put Document",
            description="Create or update a Firebase document.",
            group="Document",
            group_label="Firebase integration",
            action="firebase.doc.put",
        ),
        FirebaseCapability(
            id="firebase:doc:delete",
            label="Delete Document",
            description="Delete a Firebase document.",
            group="Document",
            group_label="Firebase integration",
            action="firebase.doc.delete",
        ),
        FirebaseCapability(
            id="firebase:doc:query",
            label="Query Documents",
            description="Run a Firebase document query.",
            group="Query",
            group_label="Firebase integration",
            action="firebase.doc.query",
        ),
        FirebaseCapability(
            id="firebase:ping",
            label="Ping",
            description="Check Firebase connectivity.",
            group="Health",
            group_label="Firebase integration",
            action="firebase.ping",
        ),
    )
)
