"""Unit tests for LlamaIndex integration — mocked, no DB required."""

from __future__ import annotations

from unittest.mock import MagicMock

import pytest

from piggie._integrations.llamaindex import PiggieGraphStore
from piggie.result import Result
from piggie.types import Edge


@pytest.fixture()
def mock_driver():
    driver = MagicMock()
    driver.graph = "test_graph"
    return driver


@pytest.fixture()
def store(mock_driver):
    return PiggieGraphStore(mock_driver, graph="test_graph")


class TestPiggieGraphStore:
    def test_client_property(self, store, mock_driver):
        assert store.client is mock_driver

    def test_upsert_triplet(self, store, mock_driver):
        store.upsert_triplet("Alice", "KNOWS", "Bob")
        mock_driver.cypher.assert_called_once()
        call_args = mock_driver.cypher.call_args
        assert "MERGE" in call_args[0][0]
        assert call_args[1]["params"] == ("Alice", "Bob", "KNOWS")
        mock_driver.commit.assert_called_once()

    def test_delete_triplet(self, store, mock_driver):
        store.delete("Alice", "KNOWS", "Bob")
        mock_driver.cypher.assert_called_once()
        call_args = mock_driver.cypher.call_args
        assert "DELETE" in call_args[0][0]
        mock_driver.commit.assert_called_once()

    def test_persist_is_noop(self, store):
        # Should not raise
        store.persist()
        store.persist("/some/path")

    def test_get_schema(self, store, mock_driver):
        mock_driver.get_schema.return_value = {
            "vertex_labels": [{"name": "Entity", "estimated_count": 10}],
            "edge_labels": [{"name": "PREDICATE", "estimated_count": 5}],
        }
        schema = store.get_schema()
        assert "Entity" in schema
        assert "PREDICATE" in schema

    def test_get_schema_cached(self, store, mock_driver):
        mock_driver.get_schema.return_value = {
            "vertex_labels": [{"name": "Entity", "estimated_count": 10}],
            "edge_labels": [],
        }
        store.get_schema()
        store.get_schema()
        # Should only call once (cached)
        mock_driver.get_schema.assert_called_once()

    def test_get_schema_refresh(self, store, mock_driver):
        mock_driver.get_schema.return_value = {
            "vertex_labels": [{"name": "Entity", "estimated_count": 10}],
            "edge_labels": [],
        }
        store.get_schema()
        store.get_schema(refresh=True)
        assert mock_driver.get_schema.call_count == 2

    def test_query(self, store, mock_driver):
        mock_driver.cypher.return_value = Result(
            [("Alice", 30)], ["name", "age"]
        )
        result = store.query("MATCH (n) RETURN n.name, n.age")
        assert "Alice" in result

    def test_get_triplets(self, store, mock_driver):
        edge = Edge(id=1, label="PREDICATE", start_id=100, end_id=200,
                     properties={"type": "KNOWS"})
        mock_driver.cypher.return_value = Result(
            [("Alice", edge, "Bob")],
            ["s_name", "r", "o_name"],
        )
        triplets = store.get("Alice")
        assert len(triplets) == 1
        assert triplets[0] == ["Alice", "KNOWS", "Bob"]
