"""Data models for fetch-by-metadata operations."""

from typing import Any

from pinecone.models._base import BaseModel
from pinecone.models._display import render_table
from pinecone.models.index._common import DataPlaneUsage, Vector, _Pagination


class FetchByMetadataRequest(BaseModel, kw_only=True):
    """Request model for fetch-by-metadata.

    Attributes:
        namespace: Target namespace.
        filter: Metadata filter expression.
        limit: Maximum number of vectors to return.
        pagination_token: Token to resume from a previous call.
    """

    namespace: str = ""
    filter: dict[str, Any] | None = None
    limit: int | None = None
    pagination_token: str | None = None


class FetchByMetadataResponse(BaseModel, kw_only=True, rename="camel"):
    """Response model for fetch-by-metadata.

    Attributes:
        vectors: Dictionary mapping vector IDs to vectors.
        namespace: Namespace fetched from.
        pagination: Pagination envelope from the API.
        usage: Read unit usage.
    """

    vectors: dict[str, Vector]
    namespace: str = ""
    pagination: _Pagination | None = None
    usage: DataPlaneUsage | None = None

    @property
    def pagination_token(self) -> str | None:
        """Token for fetching the next page, or None."""
        return self.pagination.next if self.pagination else None

    def __repr__(self) -> str:
        return f"FetchByMetadataResponse(vectors={len(self.vectors)}, namespace={self.namespace!r})"

    def __dir__(self) -> list[str]:
        """Return public API, hiding internal attributes."""
        attrs = set(super().__dir__())
        public = {name for name in attrs if not name.startswith("_")}
        return sorted(public)

    def _repr_pretty_(self, p: Any, cycle: bool) -> None:
        """IPython pretty-printer support."""
        if cycle:
            p.text("FetchByMetadataResponse(...)")
            return

        p.text("FetchByMetadataResponse(")
        with p.group(2, "", ")"):
            p.breakable()
            p.text(f"vectors={len(self.vectors)},")
            p.breakable()
            p.text(f"namespace={self.namespace!r}")
            if self.usage is not None:
                p.breakable()
                p.text(f"usage={self.usage!r}")
            if self.pagination_token is not None:
                p.breakable()
                p.text(f"pagination_token={self.pagination_token!r}")

    def _repr_html_(self) -> str:
        """Jupyter notebook HTML representation."""
        rows: list[tuple[str, str | int]] = [
            ("Vectors:", len(self.vectors)),
            ("Namespace:", self.namespace),
        ]

        if self.usage is not None:
            rows.append(("Read Units:", self.usage.read_units))
        if self.pagination_token is not None:
            rows.append(("Has More Pages:", "Yes"))

        return render_table("FetchByMetadataResponse", rows)
