"""Tests for index model display methods (_repr_html_, _repr_pretty_, __repr__)."""

from io import StringIO

from pinecone.models.indexes_old import (
    ByocSpec,
    IndexList,
    IndexModel,
    IndexSpec,
    IndexStatus,
    PodSpec,
    ServerlessReadCapacity,
    ServerlessReadCapacityStatus,
    ServerlessSpec,
)


class MockPrinter:
    """Mock IPython pretty printer for testing."""

    def __init__(self):
        self.buffer = StringIO()
        self._indent = 0

    def text(self, s: str) -> None:
        self.buffer.write(s)

    def breakable(self, sep: str = " ") -> None:
        self.buffer.write(sep)

    def group(self, indent: int, open_str: str, close_str: str):
        class Group:
            def __init__(self, printer, close_text):
                self.printer = printer
                self.close_text = close_text

            def __enter__(self):
                return self

            def __exit__(self, *args):
                self.printer.buffer.write(self.close_text)

        return Group(self, close_str)


class TestIndexModelRepr:
    """Tests for IndexModel __repr__ method."""

    def test_repr_serverless_dense_index(self):
        """Test __repr__ for serverless dense index."""
        index = IndexModel(
            name="test-index",
            metric="cosine",
            vector_type="dense",
            host="test-index-abc123.svc.pinecone.io",
            status_obj=IndexStatus(ready=True, state="Ready"),
            spec=IndexSpec(
                serverless=ServerlessSpec(
                    cloud="aws",
                    region="us-west-2",
                    read_capacity=ServerlessReadCapacity(
                        mode="on_demand",
                        status=ServerlessReadCapacityStatus(state="active"),
                    ),
                )
            ),
            dimension=768,
        )

        repr_str = repr(index)
        assert "IndexModel" in repr_str
        assert "name='test-index'" in repr_str
        assert "status='Ready'" in repr_str
        assert "dimension=768" in repr_str

    def test_repr_sparse_index(self):
        """Test __repr__ for sparse index (no dimension)."""
        index = IndexModel(
            name="sparse-index",
            metric="dotproduct",
            vector_type="sparse",
            host="sparse-index-abc123.svc.pinecone.io",
            status_obj=IndexStatus(ready=True, state="Ready"),
            spec=IndexSpec(
                serverless=ServerlessSpec(
                    cloud="aws",
                    region="us-west-2",
                    read_capacity=ServerlessReadCapacity(
                        mode="on_demand",
                        status=ServerlessReadCapacityStatus(state="active"),
                    ),
                )
            ),
            dimension=None,
        )

        repr_str = repr(index)
        assert "IndexModel" in repr_str
        assert "name='sparse-index'" in repr_str
        assert "sparse_index" in repr_str


class TestIndexModelReprPretty:
    """Tests for IndexModel _repr_pretty_ method."""

    def test_repr_pretty_shows_key_info(self):
        """Test _repr_pretty_ shows key information."""
        index = IndexModel(
            name="test-index",
            metric="cosine",
            vector_type="dense",
            host="test-index-abc123.svc.pinecone.io",
            status_obj=IndexStatus(ready=True, state="Ready"),
            spec=IndexSpec(
                serverless=ServerlessSpec(
                    cloud="aws",
                    region="us-west-2",
                    read_capacity=ServerlessReadCapacity(
                        mode="on_demand",
                        status=ServerlessReadCapacityStatus(state="active"),
                    ),
                )
            ),
            dimension=768,
        )

        p = MockPrinter()
        index._repr_pretty_(p, cycle=False)
        output = p.buffer.getvalue()

        assert "test-index" in output
        assert "Ready" in output
        assert "dimension=768" in output
        assert "cosine" in output
        assert "dense" in output

    def test_repr_pretty_handles_cycle(self):
        """Test _repr_pretty_ handles cycle detection."""
        index = IndexModel(
            name="test-index",
            metric="cosine",
            vector_type="dense",
            host="test-index-abc123.svc.pinecone.io",
            status_obj=IndexStatus(ready=True, state="Ready"),
            spec=IndexSpec(
                serverless=ServerlessSpec(
                    cloud="aws",
                    region="us-west-2",
                    read_capacity=ServerlessReadCapacity(
                        mode="on_demand",
                        status=ServerlessReadCapacityStatus(state="active"),
                    ),
                )
            ),
            dimension=768,
        )

        p = MockPrinter()
        index._repr_pretty_(p, cycle=True)
        output = p.buffer.getvalue()

        assert "IndexModel(...)" in output


class TestIndexModelReprHtml:
    """Tests for IndexModel _repr_html_ method."""

    def test_repr_html_serverless_index(self):
        """Test _repr_html_ for serverless index."""
        index = IndexModel(
            name="test-index",
            metric="cosine",
            vector_type="dense",
            host="test-index-abc123.svc.pinecone.io",
            status_obj=IndexStatus(ready=True, state="Ready"),
            spec=IndexSpec(
                serverless=ServerlessSpec(
                    cloud="aws",
                    region="us-west-2",
                    read_capacity=ServerlessReadCapacity(
                        mode="on_demand",
                        status=ServerlessReadCapacityStatus(state="active"),
                    ),
                )
            ),
            dimension=768,
            deletion_protection="disabled",
            tags={"env": "test", "team": "ml"},
        )

        html = index._repr_html_()

        assert isinstance(html, str)
        assert "test-index" in html
        assert "Ready" in html
        assert "Serverless (aws/us-west-2)" in html
        assert "768" in html
        assert "cosine" in html
        assert "dense" in html
        assert "test-index-abc123.svc.pinecone.io" in html
        assert "disabled" in html
        assert "env=test" in html
        assert "team=ml" in html

    def test_repr_html_pod_index(self):
        """Test _repr_html_ for pod-based index."""
        index = IndexModel(
            name="pod-index",
            metric="euclidean",
            vector_type="dense",
            host="pod-index-abc123.svc.pinecone.io",
            status_obj=IndexStatus(ready=True, state="Ready"),
            spec=IndexSpec(
                pod=PodSpec(
                    environment="us-west1-gcp",
                    pod_type="p1.x1",
                    pods=1,
                    replicas=1,
                    shards=1,
                )
            ),
            dimension=1536,
        )

        html = index._repr_html_()

        assert isinstance(html, str)
        assert "pod-index" in html
        assert "Pod (us-west1-gcp)" in html
        assert "1536" in html

    def test_repr_html_byoc_index(self):
        """Test _repr_html_ for BYOC index with private_host."""
        index = IndexModel(
            name="byoc-index",
            metric="cosine",
            vector_type="dense",
            host="byoc-index-abc123.svc.aped-4627-b74a.pinecone.io",
            private_host="byoc-index-abc123.svc.private.aped-4627-b74a.pinecone.io",
            status_obj=IndexStatus(ready=True, state="Ready"),
            spec=IndexSpec(
                byoc=ByocSpec(
                    environment="byoc-env-123",
                    read_capacity=ServerlessReadCapacity(
                        mode="on_demand",
                        status=ServerlessReadCapacityStatus(state="active"),
                    ),
                )
            ),
            dimension=768,
        )

        html = index._repr_html_()

        assert isinstance(html, str)
        assert "byoc-index" in html
        assert "BYOC (byoc-env-123)" in html
        assert "byoc-index-abc123.svc.aped-4627-b74a.pinecone.io" in html
        assert "byoc-index-abc123.svc.private.aped-4627-b74a.pinecone.io" in html

    def test_repr_html_sparse_index(self):
        """Test _repr_html_ for sparse index (no dimension)."""
        index = IndexModel(
            name="sparse-index",
            metric="dotproduct",
            vector_type="sparse",
            host="sparse-index-abc123.svc.pinecone.io",
            status_obj=IndexStatus(ready=True, state="Ready"),
            spec=IndexSpec(
                serverless=ServerlessSpec(
                    cloud="aws",
                    region="us-west-2",
                    read_capacity=ServerlessReadCapacity(
                        mode="on_demand",
                        status=ServerlessReadCapacityStatus(state="active"),
                    ),
                )
            ),
            dimension=None,
        )

        html = index._repr_html_()

        assert isinstance(html, str)
        assert "sparse-index" in html
        assert "N/A (sparse)" in html

    def test_repr_html_escapes_user_data(self):
        """Test _repr_html_ escapes HTML in user data."""
        index = IndexModel(
            name="<script>alert('xss')</script>",
            metric="cosine",
            vector_type="dense",
            host="test-index-abc123.svc.pinecone.io",
            status_obj=IndexStatus(ready=True, state="<b>Ready</b>"),
            spec=IndexSpec(
                serverless=ServerlessSpec(
                    cloud="aws",
                    region="us-west-2",
                    read_capacity=ServerlessReadCapacity(
                        mode="on_demand",
                        status=ServerlessReadCapacityStatus(state="active"),
                    ),
                )
            ),
            dimension=768,
            tags={"key": "<img src=x onerror=alert(1)>"},
        )

        html = index._repr_html_()

        # HTML should be escaped
        assert "<script>" not in html
        assert "&lt;script&gt;" in html
        assert "<b>Ready</b>" not in html
        assert "&lt;b&gt;Ready&lt;/b&gt;" in html
        assert "<img" not in html

    def test_repr_html_includes_embed_field(self):
        """Test _repr_html_ includes embed field when present."""
        index = IndexModel(
            name="model-index",
            metric="cosine",
            vector_type="dense",
            host="model-index-abc123.svc.pinecone.io",
            status_obj=IndexStatus(ready=True, state="Ready"),
            spec=IndexSpec(
                serverless=ServerlessSpec(
                    cloud="aws",
                    region="us-east-1",
                    read_capacity=ServerlessReadCapacity(
                        mode="OnDemand",
                        status=ServerlessReadCapacityStatus(state="Ready"),
                    ),
                )
            ),
            dimension=1024,
            embed={
                "model": "multilingual-e5-large",
                "metric": "cosine",
                "dimension": 1024,
                "field_map": {"text": "content"},
            },
        )

        html = index._repr_html_()

        # Check that embed field is displayed
        assert "Embedding Model:" in html
        assert "multilingual-e5-large" in html


class TestIndexModelDir:
    """Tests for IndexModel __dir__ method."""

    def test_dir_returns_public_only(self):
        """Test __dir__ returns only public attributes."""
        index = IndexModel(
            name="test-index",
            metric="cosine",
            vector_type="dense",
            host="test-index-abc123.svc.pinecone.io",
            status_obj=IndexStatus(ready=True, state="Ready"),
            spec=IndexSpec(
                serverless=ServerlessSpec(
                    cloud="aws",
                    region="us-west-2",
                    read_capacity=ServerlessReadCapacity(
                        mode="on_demand",
                        status=ServerlessReadCapacityStatus(state="active"),
                    ),
                )
            ),
            dimension=768,
        )

        attrs = dir(index)

        # Should include public attributes
        assert "name" in attrs
        assert "metric" in attrs
        assert "dimension" in attrs
        assert "status" in attrs
        assert "config" in attrs

        # Should not include private attributes
        assert not any(attr.startswith("_") for attr in attrs)


class TestIndexListRepr:
    """Tests for IndexList __repr__ method."""

    def test_repr_shows_count(self):
        """Test __repr__ shows index count."""
        index_list = IndexList(indexes=[])
        assert "IndexList(indexes=0)" in repr(index_list)

        index_list = IndexList(
            indexes=[
                IndexModel(
                    name="test-index",
                    metric="cosine",
                    vector_type="dense",
                    host="test-index-abc123.svc.pinecone.io",
                    status_obj=IndexStatus(ready=True, state="Ready"),
                    spec=IndexSpec(
                        serverless=ServerlessSpec(
                            cloud="aws",
                            region="us-west-2",
                            read_capacity=ServerlessReadCapacity(
                                mode="on_demand",
                                status=ServerlessReadCapacityStatus(state="active"),
                            ),
                        )
                    ),
                    dimension=768,
                )
            ]
        )
        assert "IndexList(indexes=1)" in repr(index_list)


class TestIndexListReprPretty:
    """Tests for IndexList _repr_pretty_ method."""

    def test_repr_pretty_shows_count(self):
        """Test _repr_pretty_ shows count."""
        index_list = IndexList(indexes=[])

        p = MockPrinter()
        index_list._repr_pretty_(p, cycle=False)
        output = p.buffer.getvalue()

        assert "IndexList(indexes=0)" in output

    def test_repr_pretty_handles_cycle(self):
        """Test _repr_pretty_ handles cycle detection."""
        index_list = IndexList(indexes=[])

        p = MockPrinter()
        index_list._repr_pretty_(p, cycle=True)
        output = p.buffer.getvalue()

        assert "IndexList(...)" in output


class TestIndexListReprHtml:
    """Tests for IndexList _repr_html_ method."""

    def test_repr_html_shows_count(self):
        """Test _repr_html_ shows index count."""
        index_list = IndexList(indexes=[])
        html = index_list._repr_html_()

        assert isinstance(html, str)
        assert "IndexList" in html
        assert "0" in html

        index_list = IndexList(
            indexes=[
                IndexModel(
                    name="test-index",
                    metric="cosine",
                    vector_type="dense",
                    host="test-index-abc123.svc.pinecone.io",
                    status_obj=IndexStatus(ready=True, state="Ready"),
                    spec=IndexSpec(
                        serverless=ServerlessSpec(
                            cloud="aws",
                            region="us-west-2",
                            read_capacity=ServerlessReadCapacity(
                                mode="on_demand",
                                status=ServerlessReadCapacityStatus(state="active"),
                            ),
                        )
                    ),
                    dimension=768,
                )
            ]
        )
        html = index_list._repr_html_()
        assert "1" in html


class TestIndexListDir:
    """Tests for IndexList __dir__ method."""

    def test_dir_returns_public_only(self):
        """Test __dir__ returns only public attributes."""
        index_list = IndexList(indexes=[])
        attrs = dir(index_list)

        # Should include public attributes
        assert "indexes" in attrs

        # Should not include private attributes
        assert not any(attr.startswith("_") for attr in attrs)
