import asyncio
import pytest

@pytest.mark.asyncio
async def test_stress_read_concurrent(client, tmp_path, write_file):
    path = tmp_path("test_stress_read.txt")
    write_file(path, "hello world\n" * 100)

    async def do_read(i):
        result = await client.call_tool("read_text_file", {"path": path})
        if result.is_error:
            raise RuntimeError(f"Error on read {i}: {result}")
        assert "hello world" in result.content[0].text

    # 50 concurrent reads should trigger the hanging/stuck issue if not synchronized
    tasks = [do_read(i) for i in range(50)]
    await asyncio.gather(*tasks)

@pytest.mark.asyncio
async def test_stress_edit_concurrent(client, tmp_path, write_file, read_file):
    path = tmp_path("test_stress_edit.txt")
    write_file(path, "a " * 50)

    async def do_edit(i):
        result = await client.call_tool(
            "edit_file",
            {
                "path": path,
                "edits": [{"oldText": "a", "newText": f"b{i}"}],
                "dryRun": True, # dryRun so they don't conflict functionally
            },
        )
        if result.is_error:
            raise RuntimeError(f"Error on edit {i}: {result}")
        assert "b" in result.content[0].text or "a" in result.content[0].text

    tasks = [do_edit(i) for i in range(50)]
    await asyncio.gather(*tasks)

@pytest.mark.asyncio
async def test_stress_sequential_mixed(client, tmp_path, write_file, read_file):
    path = tmp_path("test_stress_mixed.txt")
    write_file(path, "test data\n")

    for i in range(100):
        # alternating read and edit
        if i % 2 == 0:
            result = await client.call_tool("read_text_file", {"path": path})
            assert not result.is_error
        else:
            result = await client.call_tool(
                "edit_file",
                {
                    "path": path,
                    "edits": [{"oldText": "test data", "newText": "test data"}],
                    "dryRun": True,
                },
            )
            assert not result.is_error
