#!/usr/bin/env python3
"""
Tests for GraphCollection.get() — verifies the O(1) _uri_map lookup
works correctly after the optimization.

Covers: Phase 11 (GraphCollection.get() uses _uri_map)
"""

import sys
from pathlib import Path

project_root = Path(__file__).parent.parent.parent
sys.path.insert(0, str(project_root))

from vital_ai_vitalsigns.vitalsigns import VitalSigns
from vital_ai_vitalsigns.model.VITAL_Node import VITAL_Node
from vital_ai_vitalsigns.collection.graph_collection import GraphCollection


def test_collection_get_existing():
    """get() returns the object for a URI that exists in the collection."""
    vs = VitalSigns()
    gc = GraphCollection(use_rdfstore=False, use_vectordb=False)

    node = VITAL_Node()
    node.URI = "http://example.com/gc-test-1"
    node.name = "Node 1"
    gc.append(node)

    result = gc.get("http://example.com/gc-test-1")
    assert result is not None
    assert result.URI == "http://example.com/gc-test-1"
    assert result.name == "Node 1"


def test_collection_get_missing():
    """get() returns None (default) for a URI not in the collection."""
    vs = VitalSigns()
    gc = GraphCollection(use_rdfstore=False, use_vectordb=False)

    result = gc.get("http://example.com/nonexistent")
    assert result is None


def test_collection_get_default():
    """get() returns the provided default for a missing URI."""
    vs = VitalSigns()
    gc = GraphCollection(use_rdfstore=False, use_vectordb=False)

    sentinel = object()
    result = gc.get("http://example.com/nonexistent", default=sentinel)
    assert result is sentinel


def test_collection_get_multiple_objects():
    """get() finds the correct object among multiple entries."""
    vs = VitalSigns()
    gc = GraphCollection(use_rdfstore=False, use_vectordb=False)

    for i in range(5):
        node = VITAL_Node()
        node.URI = f"http://example.com/gc-multi-{i}"
        node.name = f"Node {i}"
        gc.append(node)

    result = gc.get("http://example.com/gc-multi-3")
    assert result is not None
    assert result.name == "Node 3"

    # First and last
    assert gc.get("http://example.com/gc-multi-0").name == "Node 0"
    assert gc.get("http://example.com/gc-multi-4").name == "Node 4"


def test_collection_get_after_remove():
    """get() returns None after an object is removed from the collection."""
    vs = VitalSigns()
    gc = GraphCollection(use_rdfstore=False, use_vectordb=False)

    node = VITAL_Node()
    node.URI = "http://example.com/gc-remove-test"
    node.name = "To Remove"
    gc.append(node)

    assert gc.get("http://example.com/gc-remove-test") is not None

    gc.remove("http://example.com/gc-remove-test")
    assert gc.get("http://example.com/gc-remove-test") is None


def test_collection_get_after_replace():
    """get() returns the updated object after replacement via insert."""
    vs = VitalSigns()
    gc = GraphCollection(use_rdfstore=False, use_vectordb=False)

    node1 = VITAL_Node()
    node1.URI = "http://example.com/gc-replace-test"
    node1.name = "Original"
    gc.append(node1)

    node2 = VITAL_Node()
    node2.URI = "http://example.com/gc-replace-test"
    node2.name = "Replaced"
    gc.insert(0, node2)

    result = gc.get("http://example.com/gc-replace-test")
    assert result is not None
    assert result.name == "Replaced"


def test_collection_get_with_uri_object():
    """get() works when passed a URI-like object (not just a string)."""
    vs = VitalSigns()
    gc = GraphCollection(use_rdfstore=False, use_vectordb=False)

    node = VITAL_Node()
    node.URI = "http://example.com/gc-uriobj-test"
    node.name = "URI Object Test"
    gc.append(node)

    # Pass the URI property object directly — str() conversion happens inside get()
    result = gc.get(node.URI)
    assert result is not None
    assert result.name == "URI Object Test"
