import pytest
import asyncio
from theus.engine import TheusEngine
from theus.structures import StateUpdate

# TDD: Verify CAS (Compare-And-Swap) ensures Serializability via Retry Logic


@pytest.mark.asyncio
async def test_cas_ensures_serializability():
    """
    v3.3 Behavior: Engine auto-retries conflicts instead of raising exceptions.
    This test verifies that concurrent updates to the SAME key are serialized correctly.

    Scenario:
    - Process A reads version=1, sleeps 100ms, tries to write x=1.
    - Process B reads version=1, writes x=2 immediately.
    - Process A's first attempt fails (CAS mismatch), Engine retries with new version.
    - Final Result: BOTH processes succeed. x should be the value from the LAST commit.
    """
    # v3 requires explicit domain initialization for ctx.domain to be valid dict
    engine = TheusEngine(context={"domain": {}})

    from theus.contracts import process

    # Define outputs to allow write
    # Define outputs to allow write
    @process(inputs=["domain"], outputs=["domain"])
    async def slow_process(ctx):
        # v_start = ctx.version  <-- blocked by Strict Mode
        await asyncio.sleep(0.1)
        # Check domain existence via try-except or hasattr
        if not hasattr(ctx.domain, "counter"):
            pass

        ctx.domain.counter = 1
        return 0

    @process(inputs=["domain"], outputs=["domain"])
    async def fast_process(ctx):
        # v_start = ctx.version
        ctx.domain.counter = 2
        return 0

    # Launch both
    t1 = asyncio.create_task(engine.execute(slow_process))
    t2 = asyncio.create_task(engine.execute(fast_process))

    # Both should succeed (Retry Logic handles conflicts)
    await t2  # Fast finishes first
    await t1  # Slow retries and succeeds

    # Final state: x should exist (either 1 or 2 depending on commit order)
    # The important invariant: NO exception was raised, system is live.
    # Final state: x should exist (either 1 or 2 depending on commit order)
    # The important invariant: NO exception was raised, system is live.
    final_x = engine.state.domain.counter
    assert final_x is not None, "counter should have been written"
    assert final_x in [1, 2], f"counter should be 1 or 2, got {final_x}"

    # Version should have advanced (at least 2 commits)
    assert engine.state.version >= 2, "Version should have advanced"


@pytest.mark.asyncio
async def test_cas_stress_increment():
    # 100 tasks incrementing x. Logic MUST use CAS retry loop handled by Engine or User.
    # If naive, final result < 100. If safe, final result == 100.
    # Here we test that Engine correctly serializes commits or rejects stale ones.
    pass
