#!/usr/bin/env python3
"""
Tests for multi-value property handling across all deserialization formats.
The 'types' property on VITAL_Node is multi-value (Property_types.multiple_values = True).

Covers: Phase 3 (from_triples), Phase 4 (from_json/from_dict/from_json_map),
        Phase 8 (from_rdf/from_rdf_list), Phase 10 (from_json_triples)
"""

import json
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


def _make_node_with_types():
    """Helper: create a VITAL_Node and set the multi-value 'types' property."""
    vs = VitalSigns()
    node = VITAL_Node()
    node.URI = "http://example.com/mv-test"
    node.name = "MultiValue Test"
    # 'types' is a multi-value URIProperty
    type_list = [
        "http://vital.ai/ontology/vital-core#VITAL_Node",
        "http://vital.ai/ontology/vital-core#GraphObject",
    ]
    setattr(node, "http://vital.ai/ontology/vital-core#types", type_list)
    return node, type_list


# -- JSON round-trip --

def test_multivalue_json_roundtrip():
    """Multi-value property survives JSON round-trip."""
    node, expected_types = _make_node_with_types()

    json_str = node.to_json(pretty_print=False)
    restored = VITAL_Node.from_json(json_str)

    types_uri = "http://vital.ai/ontology/vital-core#types"
    restored_prop = restored.get_property_value(types_uri)
    assert restored_prop is not None
    restored_val = restored_prop.get_value()
    # Multi-value should be a list
    assert isinstance(restored_val, list), f"Expected list, got {type(restored_val)}"
    assert set(restored_val) == set(expected_types)


def test_multivalue_json_map_roundtrip():
    """Multi-value property survives from_json_map round-trip."""
    node, expected_types = _make_node_with_types()

    dict_data = node.to_dict()
    restored = VITAL_Node.from_json_map(dict_data)

    types_uri = "http://vital.ai/ontology/vital-core#types"
    restored_prop = restored.get_property_value(types_uri)
    assert restored_prop is not None
    restored_val = restored_prop.get_value()
    assert isinstance(restored_val, list), f"Expected list, got {type(restored_val)}"
    assert set(restored_val) == set(expected_types)


# -- Dict round-trip --

def test_multivalue_dict_roundtrip():
    """Multi-value property survives dict round-trip."""
    node, expected_types = _make_node_with_types()

    dict_data = node.to_dict()
    restored = VITAL_Node.from_dict(dict_data)

    types_uri = "http://vital.ai/ontology/vital-core#types"
    restored_prop = restored.get_property_value(types_uri)
    assert restored_prop is not None
    restored_val = restored_prop.get_value()
    assert isinstance(restored_val, list), f"Expected list, got {type(restored_val)}"
    assert set(restored_val) == set(expected_types)


# -- RDF round-trip --

def test_multivalue_rdf_roundtrip():
    """Multi-value property survives RDF (nt) round-trip."""
    node, expected_types = _make_node_with_types()

    rdf_str = node.to_rdf(format='nt')
    restored = VITAL_Node.from_rdf(rdf_str)

    types_uri = "http://vital.ai/ontology/vital-core#types"
    restored_prop = restored.get_property_value(types_uri)
    assert restored_prop is not None
    restored_val = restored_prop.get_value()
    assert isinstance(restored_val, list), f"Expected list, got {type(restored_val)}"
    assert set(restored_val) == set(expected_types)


def test_multivalue_rdf_list_roundtrip():
    """Multi-value property survives from_rdf_list round-trip with multiple objects."""
    vs = VitalSigns()

    node1, types1 = _make_node_with_types()
    node2 = VITAL_Node()
    node2.URI = "http://example.com/mv-test-2"
    node2.name = "MultiValue Test 2"

    rdf1 = node1.to_rdf(format='nt')
    rdf2 = node2.to_rdf(format='nt')
    combined = rdf1 + "\n" + rdf2

    restored_list = VITAL_Node.from_rdf_list(combined)
    assert len(restored_list) == 2

    # Find the one with multi-value types
    mv_node = None
    for r in restored_list:
        if str(r.URI) == "http://example.com/mv-test":
            mv_node = r
            break
    assert mv_node is not None

    types_uri = "http://vital.ai/ontology/vital-core#types"
    restored_prop = mv_node.get_property_value(types_uri)
    assert restored_prop is not None
    restored_val = restored_prop.get_value()
    assert isinstance(restored_val, list), f"Expected list, got {type(restored_val)}"
    assert set(restored_val) == set(types1)


# -- Triples round-trip --

def test_multivalue_triples_roundtrip():
    """Multi-value property survives triples round-trip."""
    node, expected_types = _make_node_with_types()

    triple_list = []
    node.add_to_list(triple_list)

    def gen():
        for t in triple_list:
            yield t

    restored = VITAL_Node.from_triples(gen())

    types_uri = "http://vital.ai/ontology/vital-core#types"
    restored_prop = restored.get_property_value(types_uri)
    assert restored_prop is not None
    restored_val = restored_prop.get_value()
    assert isinstance(restored_val, list), f"Expected list, got {type(restored_val)}"
    assert set(restored_val) == set(expected_types)


def test_multivalue_triples_list_roundtrip():
    """Multi-value property survives from_triples_list round-trip."""
    node, expected_types = _make_node_with_types()

    triple_list = []
    node.add_to_list(triple_list)

    def gen():
        for t in triple_list:
            yield t

    restored_list = VITAL_Node.from_triples_list(gen())
    assert len(restored_list) >= 1

    types_uri = "http://vital.ai/ontology/vital-core#types"
    restored_prop = restored_list[0].get_property_value(types_uri)
    assert restored_prop is not None
    restored_val = restored_prop.get_value()
    assert isinstance(restored_val, list), f"Expected list, got {type(restored_val)}"
    assert set(restored_val) == set(expected_types)
