"""Integration tests for vector upsert with tuple formats.

These tests verify that the SDK correctly handles tuple formats for backward
compatibility with prior versions of the SDK.

Setup:
    export PINECONE_API_KEY="your-api-key"
    export PINECONE_TEST_INDEX_HOST="your-index-host.svc.pinecone.io"
    pytest tests/integration/test_upsert_formats.py -v

Note: Integration tests require a real index and may incur API costs.
"""

from __future__ import annotations

import os

import pytest

from pinecone import Index


pytestmark = pytest.mark.integration


@pytest.fixture()
def test_index() -> Index:
    """Get test index for data plane operations.

    Returns:
        Index client for testing.

    Raises:
        pytest.skip: If required environment variables are not set.
    """
    api_key = os.getenv("PINECONE_API_KEY")
    index_host = os.getenv("PINECONE_TEST_INDEX_HOST")

    if not api_key:
        pytest.skip("PINECONE_API_KEY not set")
    if not index_host:
        pytest.skip("PINECONE_TEST_INDEX_HOST not set")

    return Index(host=index_host, api_key=api_key)


class TestUpsertTupleFormats:
    """Test upsert with tuple formats from prior SDK versions."""

    def test_upsert_2_tuple_format(self, test_index: Index, test_namespace: str) -> None:
        """Test upsert with 2-tuple format (id, values).

        Args:
            test_index: The test index fixture.
            test_namespace: Unique test namespace.
        """
        # Upsert with 2-tuple format
        response = test_index.upsert(
            vectors=[("tuple-2-a", [0.1] * 768), ("tuple-2-b", [0.2] * 768)],
            namespace=test_namespace,
        )

        assert response.upserted_count == 2

        # Verify vectors were stored correctly
        fetch_result = test_index.fetch(ids=["tuple-2-a", "tuple-2-b"], namespace=test_namespace)
        assert len(fetch_result.vectors) == 2
        assert "tuple-2-a" in fetch_result.vectors
        assert "tuple-2-b" in fetch_result.vectors

        # Cleanup
        test_index.delete(delete_all=True, namespace=test_namespace)

    def test_upsert_3_tuple_format(self, test_index: Index, test_namespace: str) -> None:
        """Test upsert with 3-tuple format (id, values, metadata).

        Args:
            test_index: The test index fixture.
            test_namespace: Unique test namespace.
        """
        # Upsert with 3-tuple format including metadata
        response = test_index.upsert(
            vectors=[
                ("tuple-3-a", [0.3] * 768, {"format": "3-tuple", "category": "test"}),
                ("tuple-3-b", [0.4] * 768, {"format": "3-tuple", "number": 42}),
            ],
            namespace=test_namespace,
        )

        assert response.upserted_count == 2

        # Verify vectors and metadata were stored correctly
        fetch_result = test_index.fetch(ids=["tuple-3-a", "tuple-3-b"], namespace=test_namespace)
        assert len(fetch_result.vectors) == 2

        # Check first vector metadata
        vec_a = fetch_result.vectors["tuple-3-a"]
        assert vec_a.metadata is not None
        assert vec_a.metadata["format"] == "3-tuple"
        assert vec_a.metadata["category"] == "test"

        # Check second vector metadata
        vec_b = fetch_result.vectors["tuple-3-b"]
        assert vec_b.metadata is not None
        assert vec_b.metadata["format"] == "3-tuple"
        assert vec_b.metadata["number"] == 42

        # Cleanup
        test_index.delete(delete_all=True, namespace=test_namespace)

    def test_upsert_mixed_formats(self, test_index: Index, test_namespace: str) -> None:
        """Test upsert with mixed dict and tuple formats.

        Args:
            test_index: The test index fixture.
            test_namespace: Unique test namespace.
        """
        # Mix all supported formats in one upsert call
        response = test_index.upsert(
            vectors=[
                ("tuple-2", [0.5] * 768),  # 2-tuple
                ("tuple-3", [0.6] * 768, {"type": "tuple"}),  # 3-tuple
                {"id": "dict", "values": [0.7] * 768, "metadata": {"type": "dict"}},  # dict
            ],
            namespace=test_namespace,
        )

        assert response.upserted_count == 3

        # Verify all formats were processed correctly
        fetch_result = test_index.fetch(
            ids=["tuple-2", "tuple-3", "dict"], namespace=test_namespace
        )
        assert len(fetch_result.vectors) == 3

        # Verify 2-tuple (no metadata)
        assert "tuple-2" in fetch_result.vectors
        vec_2 = fetch_result.vectors["tuple-2"]
        assert vec_2.metadata is None or vec_2.metadata == {}

        # Verify 3-tuple metadata
        vec_3 = fetch_result.vectors["tuple-3"]
        assert vec_3.metadata is not None
        assert vec_3.metadata["type"] == "tuple"

        # Verify dict metadata
        vec_dict = fetch_result.vectors["dict"]
        assert vec_dict.metadata is not None
        assert vec_dict.metadata["type"] == "dict"

        # Cleanup
        test_index.delete(delete_all=True, namespace=test_namespace)

    def test_upsert_tuple_with_query(self, test_index: Index, test_namespace: str) -> None:
        """Test that tuples work correctly with query operations.

        Args:
            test_index: The test index fixture.
            test_namespace: Unique test namespace.
        """
        # Upsert with tuple format
        query_vector = [0.8] * 768
        test_index.upsert(
            vectors=[
                ("queryable-1", query_vector, {"category": "search"}),
                ("queryable-2", [0.9] * 768, {"category": "other"}),
            ],
            namespace=test_namespace,
        )

        # Query for similar vectors
        results = test_index.query(
            vector=query_vector,
            top_k=2,
            namespace=test_namespace,
            include_metadata=True,
        )

        # Should find the vectors we upserted
        assert len(results.matches) > 0
        ids = [match.id for match in results.matches]
        assert "queryable-1" in ids

        # Cleanup
        test_index.delete(delete_all=True, namespace=test_namespace)

    def test_upsert_tuple_preserves_dict_compatibility(
        self, test_index: Index, test_namespace: str
    ) -> None:
        """Test that tuple support doesn't break existing dict-based code.

        Args:
            test_index: The test index fixture.
            test_namespace: Unique test namespace.
        """
        # Use the recommended dict format
        response = test_index.upsert(
            vectors=[
                {"id": "dict-v1", "values": [0.11] * 768, "metadata": {"key": "value"}},
                {"id": "dict-v2", "values": [0.12] * 768},
            ],
            namespace=test_namespace,
        )

        assert response.upserted_count == 2

        # Verify dict format still works correctly
        fetch_result = test_index.fetch(ids=["dict-v1", "dict-v2"], namespace=test_namespace)
        assert len(fetch_result.vectors) == 2
        assert fetch_result.vectors["dict-v1"].metadata == {"key": "value"}

        # Cleanup
        test_index.delete(delete_all=True, namespace=test_namespace)
