import pytest

from mcard.model.pcard import PCard


@pytest.fixture
def pcard_a():
    content = """
    chapter:
      id: function_a
      title: Function A
    clm:
      abstract:
        type: int -> str
      concrete:
        runtime: python
        operation: str
    """
    return PCard(content)


@pytest.fixture
def pcard_b():
    content = """
    chapter:
      id: function_b
      title: Function B
    clm:
      abstract:
        type: str -> json
      concrete:
        runtime: python
        operation: json.loads
    """
    return PCard(content)


def test_sequential_composition(pcard_a, pcard_b):
    """Test A.then(B) creates valid composition."""
    pcard_c = pcard_a.then(pcard_b)

    assert isinstance(pcard_c, PCard)
    clm = pcard_c.clm

    # Check abstract structure inside nested 'clm' or root
    abstract = clm.get("clm", {}).get("abstract", {})
    assert abstract.get("type") == "sequential_composition"
    assert abstract.get("steps") == [pcard_a.hash, pcard_b.hash]


def test_tensor_product(pcard_a, pcard_b):
    """Test A.and_also(B) creates valid parallel execution."""
    pcard_c = pcard_a.and_also(pcard_b)

    abstract = pcard_c.clm.get("clm", {}).get("abstract", {})
    assert abstract.get("type") == "tensor_product"
    assert abstract.get("left") == pcard_a.hash
    assert abstract.get("right") == pcard_b.hash


def test_symmetry_swap(pcard_a):
    """Test A.swap() creates valid symmetry application."""
    pcard_b = pcard_a.swap()

    abstract = pcard_b.clm.get("clm", {}).get("abstract", {})
    assert abstract.get("type") == "symmetry_swap"
    assert abstract.get("target") == pcard_a.hash


def test_universal_tooling_interface(pcard_a):
    """Test standard tooling methods enable O(1) toolchain."""

    # Verify
    verification = pcard_a.verify()
    assert verification["status"] == "pending_verification"
    assert verification["target"] == pcard_a.hash

    # Profile
    profile = pcard_a.profile()
    assert profile["status"] == "profiling_ready"

    # Debug
    debug = pcard_a.debug()
    assert debug["status"] == "debug_session_created"

    # Explain
    explanation = pcard_a.explain()
    assert explanation["abstract"]["type"] == "int -> str"
