import pytest
from aceiot_cim_rdf.conversion import parse_raw, convert_to_cim, metadata_for_raw_source
from aceiot_cim_rdf.cim_pydantic.base import serialize_to_turtle, deserialize_from_turtle
from rdflib import Graph, URIRef
from rdflib.compare import isomorphic

def test_ieee14_conversion():
    raw_file = "IEEE 14-Bus System/IEEE 14 bus.raw"
    data = parse_raw(raw_file)
    
    # Check data counts from RAW
    assert len(data["buses"]) == 14
    assert len(data["loads"]) == 11
    assert len(data["generators"]) == 5
    assert len(data["branches"]) == 17
    assert len(data["transformers"]) == 3
    assert len(data["shunts"]) == 1

    objects = convert_to_cim(data)
    
    # Check CIM object counts
    # 14 Substations, 14 VoltageLevels, 14 ConnectivityNodes, 14 TopologicalNodes = 56
    # 11 EnergyConsumers + 11 Terminals = 22
    # 5 SynchronousMachines + 5 GeneratingUnits + 5 Terminals = 15
    # 17 ACLineSegments + 34 Terminals = 51
    # 3 PowerTransformers + 6 PowerTransformerEnds + 6 Terminals = 15
    # 1 LinearShuntCompensator + 1 Terminal + 1 Simple_Float = 3
    # 1 BaseVoltage = 1
    # Total: 56 + 22 + 15 + 51 + 15 + 3 + 1 = 163
    assert len(objects) == 163

def test_roundtrip_isomorphism():
    raw_file = "IEEE 14-Bus System/IEEE 14 bus.raw"
    data = parse_raw(raw_file)
    objects1 = convert_to_cim(data)
    
    ttl1 = serialize_to_turtle(objects1)
    objects2 = deserialize_from_turtle(ttl1)
    
    # Second serialization to compare graphs
    ttl2 = serialize_to_turtle(objects2)
    
    g1 = Graph().parse(data=ttl1, format="turtle")
    g2 = Graph().parse(data=ttl2, format="turtle")
    
    assert isomorphic(g1, g2), "Graphs are not isomorphic after round-trip"

def test_specific_component_values():
    raw_file = "IEEE 14-Bus System/IEEE 14 bus.raw"
    data = parse_raw(raw_file)
    objects = convert_to_cim(data)
    
    # Check a specific line
    lines = [o for o in objects if o.__class__.__name__ == "ACLineSegment"]
    line1_2 = next(l for l in lines if l.name == "Line 1-2")
    assert line1_2.r == 0.01938
    assert line1_2.x == 0.05917
    
    # Check the shunt
    shunts = [o for o in objects if o.__class__.__name__ == "LinearShuntCompensator"]
    assert len(shunts) == 1
    assert shunts[0].bPerSection == 19.0

def test_transformer_regression():
    raw_file = "IEEE 14-Bus System/IEEE 14 bus.raw"
    data = parse_raw(raw_file)
    objects = convert_to_cim(data)
    
    transformers = [o for o in objects if o.__class__.__name__ == "PowerTransformer"]
    assert len(transformers) == 3
    
    # Check Trans 4-7
    trans_4_7 = next(t for t in transformers if t.name == "Trans 4-7")
    
    # Find its ends
    ends = [o for o in objects if o.__class__.__name__ == "PowerTransformerEnd" and o.PowerTransformer == trans_4_7]
    assert len(ends) == 2
    
    # Side 1 (from bus 4) should have r, x
    end1 = next(e for e in ends if e.name == "TransEnd 1 0") # First trans in RAW
    assert end1.x == 0.20912
    assert end1.r == 0.0

def test_ieee14_metadata_is_serialized():
    raw_file = "IEEE 14-Bus System/IEEE 14 bus.raw"
    data = parse_raw(raw_file)
    objects = convert_to_cim(data)
    ttl = serialize_to_turtle(objects, metadata=metadata_for_raw_source(raw_file))

    graph = Graph().parse(data=ttl, format="turtle")
    dataset = URIRef("urn:aceiot-cim-rdf:dataset:ieee-14-bus")

    assert (
        dataset,
        URIRef("http://purl.org/dc/terms/source"),
        URIRef("https://electricgrids.engr.tamu.edu/electric-grid-test-cases/ieee-14-bus-system/"),
    ) in graph
    assert (
        dataset,
        URIRef("http://purl.org/dc/terms/creator"),
        None,
    ) in graph
    assert (
        dataset,
        URIRef("http://purl.org/dc/terms/references"),
        URIRef("http://labs.ece.uw.edu/pstca/pf14/pg_tca14bus.htm"),
    ) in graph
