"""Integration tests for LangChain integration — requires live PG18+AGE."""

from __future__ import annotations

import uuid
from types import SimpleNamespace
from unittest.mock import MagicMock

import pytest

pytestmark = pytest.mark.integration

import piggie  # noqa: E402
from piggie._integrations.langchain import PiggieGraphStore, PiggieVectorStore  # noqa: E402

DSN = "host=/var/run/postgresql port=5433 dbname=piggie user=gregf"


@pytest.fixture()
def driver():
    graph_name = f"test_lc_{uuid.uuid4().hex[:8]}"
    db = piggie.connect(DSN, graph=graph_name)
    yield db
    try:
        db.drop_graph(graph_name)
        db.commit()
    except Exception:
        db.rollback()
    db.close()


# ---------------------------------------------------------------------------
# PiggieVectorStore integration
# ---------------------------------------------------------------------------


class TestPiggieVectorStoreIntegration:
    @pytest.fixture()
    def table_name(self):
        return f"test_vs_{uuid.uuid4().hex[:8]}"

    @pytest.fixture()
    def mock_embedding(self):
        emb = MagicMock()
        emb.embed_documents.return_value = [[0.1, 0.2, 0.3]]
        emb.embed_query.return_value = [0.1, 0.2, 0.3]
        return emb

    @pytest.fixture(autouse=True)
    def cleanup_table(self, driver, table_name):
        yield
        try:
            driver.sql(f"DROP TABLE IF EXISTS {table_name}")
            driver.commit()
        except Exception:
            driver.rollback()

    def test_add_search_delete(self, driver, mock_embedding, table_name):
        vs = PiggieVectorStore(
            driver, mock_embedding,
            table=table_name,
            create_table=True,
            embedding_dimensions=3,
        )

        # Add texts
        ids = vs.add_texts(
            ["hello world"], metadatas=[{"source": "test"}], ids=["doc1"],
        )
        assert ids == ["doc1"]

        # Search
        docs = vs.similarity_search("hello", k=1)
        assert len(docs) == 1
        assert docs[0].page_content == "hello world"

        # Search by vector
        docs = vs.similarity_search_by_vector([0.1, 0.2, 0.3], k=1)
        assert len(docs) == 1

        # Delete
        result = vs.delete(ids=["doc1"])
        assert result is True

        # Verify gone
        docs = vs.similarity_search("hello", k=1)
        assert len(docs) == 0


# ---------------------------------------------------------------------------
# PiggieGraphStore integration
# ---------------------------------------------------------------------------


class TestPiggieGraphStoreIntegration:
    def test_add_and_query_graph_documents(self, driver):
        gs = PiggieGraphStore(driver, graph=driver.graph)

        node_a = SimpleNamespace(id="alice", type="Person", properties={"name": "Alice"})
        node_b = SimpleNamespace(id="bob", type="Person", properties={"name": "Bob"})
        rel = SimpleNamespace(
            source=SimpleNamespace(id="alice", type="Person"),
            target=SimpleNamespace(id="bob", type="Person"),
            type="KNOWS",
        )
        doc = SimpleNamespace(nodes=[node_a, node_b], relationships=[rel])
        gs.add_graph_documents([doc])

        # Query
        result = gs.query("MATCH (n:Person) RETURN n.name")
        names = [r.get("name") or r.get("n.name", "") for r in result]
        assert len(names) >= 2

    def test_get_schema(self, driver):
        gs = PiggieGraphStore(driver, graph=driver.graph)

        # Create some data first
        node = SimpleNamespace(id="x", type="Widget", properties={"val": "1"})
        doc = SimpleNamespace(nodes=[node], relationships=[])
        gs.add_graph_documents([doc])

        schema = gs.get_schema
        assert "Widget" in schema

    def test_get_structured_schema(self, driver):
        gs = PiggieGraphStore(driver, graph=driver.graph)

        node = SimpleNamespace(id="y", type="Gadget", properties={"size": "large"})
        doc = SimpleNamespace(nodes=[node], relationships=[])
        gs.add_graph_documents([doc])

        ss = gs.get_structured_schema
        assert "node_props" in ss
        assert "rel_props" in ss
        assert "relationships" in ss
