"""Index models for API responses (2026-01.alpha API).

Note for IPython/Jupyter: Autoreload can fail for this module because
msgspec.Struct instances do not support __class__ reassignment. If you see
a TypeError on reload, run ``%aimport -pinecone.models.indexes.index`` to
exclude it from autoreload, or restart the kernel after editing.
"""

from __future__ import annotations

from typing import Any

from pinecone.models._base import BaseModel
from pinecone.models._display import render_table

from .deployment import Deployment  # noqa: TC001
from .read_capacity import ReadCapacityResponse  # noqa: TC001
from .schema import Schema  # noqa: TC001


class IndexStatus(BaseModel):
    """Index status information.

    Describes the current operational state of an index.

    Attributes:
        ready: Whether the index is ready to serve queries
        state: Current state ("Ready", "Initializing", "ScalingUp", "ScalingDown", "Terminating")

    Example:
        >>> status = IndexStatus(ready=True, state="Ready")
    """

    ready: bool
    state: str  # Ready, Initializing, ScalingUp, ScalingDown, Terminating


class IndexModel(BaseModel):
    """Index description from API.

    Complete description of an index including its schema, deployment
    configuration, and operational status.

    Attributes:
        name: Index name
        schema: Field-level schema definition
        deployment: Deployment configuration (managed/pod/byoc)
        host: Index host for data plane operations
        status: Current operational status
        deletion_protection: Deletion protection setting ("enabled" or "disabled")
        read_capacity: Read capacity configuration (managed indexes only)
        private_host: Private endpoint host (if configured)
        tags: User-defined tags as key-value pairs
        source_collection: Source collection if created from collection

    Example:
        >>> index = IndexModel(
        ...     name="my-index",
        ...     schema=Schema(fields={...}),
        ...     deployment=ManagedDeployment(
        ...         environment="aped-4627-b74a", cloud="aws", region="us-east-1"
        ...     ),
        ...     host="my-index-abc123.svc.us-east-1-aws.pinecone.io",
        ...     status=IndexStatus(ready=True, state="Ready"),
        ...     deletion_protection="disabled",
        ... )
    """

    name: str
    schema: Schema
    deployment: Deployment
    host: str
    status: IndexStatus
    deletion_protection: str  # enabled, disabled
    read_capacity: ReadCapacityResponse | None = None
    private_host: str | None = None
    tags: dict[str, str] | None = None
    source_collection: str | None = None

    def __repr__(self) -> str:
        """Return summary representation."""
        dep_name = type(self.deployment).__name__.replace("Deployment", "")
        parts = [
            f"name={self.name!r}",
            f"status={self.status.state!r}",
            f"host={self.host!r}",
            f"deployment={dep_name!r}",
            f"deletion_protection={self.deletion_protection!r}",
        ]
        if self.schema.fields:
            parts.append(f"schema_fields={len(self.schema.fields)}")
        if self.private_host is not None:
            parts.append(f"private_host={self.private_host!r}")
        if self.tags:
            parts.append(f"tags={len(self.tags)} items")
        if self.source_collection is not None:
            parts.append(f"source_collection={self.source_collection!r}")
        return f"IndexModel({', '.join(parts)})"

    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:
        """Pretty-printer support for IPython."""
        if cycle:
            p.text("IndexModel(...)")
            return
        p.text("IndexModel(")
        with p.group(2, "", ")"):
            p.breakable()
            p.text(f"name={self.name!r},")
            p.breakable()
            p.text(f"status={self.status.state!r},")
            p.breakable()
            p.text(f"host={self.host!r},")
            p.breakable()
            p.text(f"deployment={self.deployment!r},")
            p.breakable()
            p.text(f"deletion_protection={self.deletion_protection!r},")
            p.breakable()
            p.text(f"schema=Schema(fields={len(self.schema.fields)} fields),")
            if self.private_host is not None:
                p.breakable()
                p.text(f"private_host={self.private_host!r},")
            if self.read_capacity is not None:
                p.breakable()
                p.text(f"read_capacity={self.read_capacity!r},")
            if self.tags:
                p.breakable()
                p.text(f"tags={self.tags!r},")
            if self.source_collection is not None:
                p.breakable()
                p.text(f"source_collection={self.source_collection!r}")

    def _repr_html_(self) -> str:
        """Jupyter notebook HTML representation."""
        dep_name = type(self.deployment).__name__.replace("Deployment", "")
        dep_detail = ""
        if hasattr(self.deployment, "cloud") and hasattr(self.deployment, "region"):
            dep_detail = f" ({getattr(self.deployment, 'cloud', '')}/{getattr(self.deployment, 'region', '')})"
        elif hasattr(self.deployment, "environment"):
            dep_detail = f" ({getattr(self.deployment, 'environment', '')})"

        rows: list[tuple[str, str | int]] = [
            ("Name:", self.name),
            ("Status:", self.status.state),
            ("Ready:", "Yes" if self.status.ready else "No"),
            ("Deployment:", f"{dep_name}{dep_detail}"),
            ("Host:", self.host),
            ("Deletion Protection:", self.deletion_protection),
            ("Schema fields:", len(self.schema.fields)),
        ]
        if self.private_host is not None:
            rows.append(("Private Host:", self.private_host))
        if self.read_capacity is not None:
            rows.append(
                ("Read capacity:", getattr(self.read_capacity, "mode", str(self.read_capacity)))
            )
        if self.tags:
            tags_str = ", ".join(f"{k}={v}" for k, v in self.tags.items())
            rows.append(("Tags:", tags_str))
        if self.source_collection is not None:
            rows.append(("Source collection:", self.source_collection))
        return render_table("IndexModel", rows)


class IndexList(BaseModel):
    """List of indexes.

    Response from listing all indexes in a project.

    Attributes:
        indexes: List of index descriptions

    Example:
        >>> index_list = IndexList(
        ...     indexes=[
        ...         IndexModel(name="index-1", ...),
        ...         IndexModel(name="index-2", ...),
        ...     ]
        ... )
    """

    indexes: list[IndexModel]


__all__ = [
    "IndexList",
    "IndexModel",
    "IndexStatus",
]
