"""Tests for resources/jobs.py."""

from __future__ import annotations

import httpx
import pytest
import respx

from murmr._client import AsyncMurmrClient, MurmrClient
from murmr._errors import MurmrError

BASE_URL = "https://api.murmr.dev"


class TestAsyncJobs:
    @respx.mock
    @pytest.mark.asyncio
    async def test_get_job_status(self) -> None:
        respx.get(f"{BASE_URL}/v1/jobs/job_abc123").mock(
            return_value=httpx.Response(
                200,
                json={
                    "id": "job_abc123",
                    "status": "completed",
                    "created_at": "2025-01-01T00:00:00Z",
                    "completed_at": "2025-01-01T00:00:05Z",
                    "duration_ms": 5000,
                    "error": None,
                    "audio_base64": "AAAA",
                    "content_type": "audio/wav",
                },
            )
        )

        async with AsyncMurmrClient(api_key="test_key", base_url=BASE_URL) as client:
            status = await client.jobs.get("job_abc123")
            assert status.id == "job_abc123"
            assert status.status == "completed"
            assert status.duration_ms == 5000

    @respx.mock
    @pytest.mark.asyncio
    async def test_get_invalid_job_id(self) -> None:
        async with AsyncMurmrClient(api_key="test_key", base_url=BASE_URL) as client:
            with pytest.raises(MurmrError, match="Invalid jobId"):
                await client.jobs.get("bad/id")

    @respx.mock
    @pytest.mark.asyncio
    async def test_wait_for_completion_already_done(self) -> None:
        respx.get(f"{BASE_URL}/v1/jobs/job_done").mock(
            return_value=httpx.Response(
                200,
                json={
                    "id": "job_done",
                    "status": "completed",
                    "created_at": "2025-01-01T00:00:00Z",
                    "completed_at": "2025-01-01T00:00:05Z",
                    "error": None,
                },
            )
        )

        async with AsyncMurmrClient(api_key="test_key", base_url=BASE_URL) as client:
            status = await client.jobs.wait_for_completion("job_done")
            assert status.status == "completed"

    @respx.mock
    @pytest.mark.asyncio
    async def test_wait_for_completion_job_failed(self) -> None:
        respx.get(f"{BASE_URL}/v1/jobs/job_fail").mock(
            return_value=httpx.Response(
                200,
                json={
                    "id": "job_fail",
                    "status": "failed",
                    "created_at": "2025-01-01T00:00:00Z",
                    "error": "GPU out of memory",
                },
            )
        )

        async with AsyncMurmrClient(api_key="test_key", base_url=BASE_URL) as client:
            with pytest.raises(MurmrError, match="GPU out of memory"):
                await client.jobs.wait_for_completion("job_fail")

    @respx.mock
    @pytest.mark.asyncio
    async def test_wait_calls_on_poll(self) -> None:
        respx.get(f"{BASE_URL}/v1/jobs/job_poll").mock(
            return_value=httpx.Response(
                200,
                json={
                    "id": "job_poll",
                    "status": "completed",
                    "created_at": "2025-01-01T00:00:00Z",
                    "error": None,
                },
            )
        )

        poll_calls: list[str] = []
        async with AsyncMurmrClient(api_key="test_key", base_url=BASE_URL) as client:
            await client.jobs.wait_for_completion(
                "job_poll", on_poll=lambda s: poll_calls.append(s.status)
            )
            assert len(poll_calls) == 1
            assert poll_calls[0] == "completed"


class TestSyncJobs:
    @respx.mock
    def test_get_job_status(self) -> None:
        respx.get(f"{BASE_URL}/v1/jobs/job_sync").mock(
            return_value=httpx.Response(
                200,
                json={
                    "id": "job_sync",
                    "status": "queued",
                    "created_at": "2025-01-01T00:00:00Z",
                    "error": None,
                },
            )
        )

        with MurmrClient(api_key="test_key", base_url=BASE_URL) as client:
            status = client.jobs.get("job_sync")
            assert status.id == "job_sync"
            assert status.status == "queued"

    @respx.mock
    def test_wait_for_completion_sync(self) -> None:
        respx.get(f"{BASE_URL}/v1/jobs/job_sync_done").mock(
            return_value=httpx.Response(
                200,
                json={
                    "id": "job_sync_done",
                    "status": "completed",
                    "created_at": "2025-01-01T00:00:00Z",
                    "completed_at": "2025-01-01T00:00:03Z",
                    "error": None,
                },
            )
        )

        with MurmrClient(api_key="test_key", base_url=BASE_URL) as client:
            status = client.jobs.wait_for_completion("job_sync_done")
            assert status.status == "completed"
