from uuid import UUID
from unittest.mock import AsyncMock

import pytest

from dsg_core_client import DSGCoreClient
from dsg_core_client.schemas import CommandDryRunRequest, CommandTypes


@pytest.mark.asyncio
async def test_start_dryrun_commands_calls_job_endpoint() -> None:
    client = DSGCoreClient(base_url="https://example.org", token="token")
    try:
        client.post = AsyncMock(return_value={"jobId": "job-123"})  # type: ignore[method-assign]

        commands = [
            CommandDryRunRequest(
                item_type_id=UUID("00000000-0000-0000-0000-000000000001"),
                version="1.0",
                command_type=CommandTypes.CREATE,
                data={"foo": "bar"},
            )
        ]

        response = await client.commands.start_dryrun_commands(commands)

        assert response.job_id == "job-123"
        client.post.assert_awaited_once_with(
            client.path("/commands/data/dry-run"),
            json=[client.dump(command) for command in commands],
        )
    finally:
        await client.close()


@pytest.mark.asyncio
async def test_get_dryrun_commands_result_waits_and_fetches() -> None:
    client = DSGCoreClient(base_url="https://example.org", token="token")
    try:
        client.get = AsyncMock(return_value={"commands": []})  # type: ignore[method-assign]
        client.bgtasks.wait_for_task = AsyncMock()  # type: ignore[method-assign]

        response = await client.commands.get_dryrun_commands_result("job-456")

        assert response.commands == []
        client.bgtasks.wait_for_task.assert_awaited_once_with(
            job_id="job-456",
            timeout_seconds=300.0,
            poll_interval_seconds=1.0,
        )
        client.get.assert_awaited_once_with(
            client.path("/commands/data/dry-run/job-456")
        )
    finally:
        await client.close()


@pytest.mark.asyncio
async def test_dryrun_commands_starts_job_then_fetches_result() -> None:
    client = DSGCoreClient(base_url="https://example.org", token="token")
    try:
        client.post = AsyncMock(return_value={"jobId": "job-789"})  # type: ignore[method-assign]
        client.get = AsyncMock(return_value={"commands": []})  # type: ignore[method-assign]
        client.bgtasks.wait_for_task = AsyncMock()  # type: ignore[method-assign]

        commands = [
            CommandDryRunRequest(
                item_type_id=UUID("00000000-0000-0000-0000-000000000001"),
                version="1.0",
                command_type=CommandTypes.UPDATE,
                data={"foo": "baz"},
            )
        ]

        response = await client.commands.dryrun_commands(commands)

        assert response.commands == []
        client.post.assert_awaited_once_with(
            client.path("/commands/data/dry-run"),
            json=[client.dump(command) for command in commands],
        )
        client.bgtasks.wait_for_task.assert_awaited_once_with(
            job_id="job-789",
            timeout_seconds=300.0,
            poll_interval_seconds=1.0,
        )
        client.get.assert_awaited_once_with(
            client.path("/commands/data/dry-run/job-789")
        )
    finally:
        await client.close()
