"""Tests for loom.orchestration.sweeper — claim TTL expiration sweep."""

from __future__ import annotations

import asyncio

import pytest

from loom.bus import channels
from loom.graph import store
from loom.graph.task import Task, TaskStatus
from loom.ids import task_id as gen_task_id
from loom.orchestration.sweeper import sweep_expired_claims


# ---------------------------------------------------------------------------
# Test 1: sweep returns 0 when no expired claims
# ---------------------------------------------------------------------------


@pytest.mark.asyncio
async def test_sweep_returns_zero_when_no_expired_claims(pool, redis_conn, project):
    """With no expired claims, sweep returns 0."""
    count = await sweep_expired_claims(pool, redis_conn, project)
    assert count == 0


# ---------------------------------------------------------------------------
# Test 2: sweep releases expired claims
# ---------------------------------------------------------------------------


@pytest.mark.asyncio
async def test_sweep_releases_expired_claims(pool, redis_conn, project):
    """A task claimed with a short TTL gets released after expiry."""
    task = Task(id=gen_task_id(), project_id=project, title="Expiring claim")
    task = await store.create_task(pool, task)
    task = await store.claim_task(pool, task.id, "agent-1", ttl_seconds=1)

    assert task.status == TaskStatus.CLAIMED
    assert task.claim_expires_at is not None

    # Wait for the TTL to expire
    await asyncio.sleep(1.1)

    count = await sweep_expired_claims(pool, redis_conn, project)
    assert count == 1

    # Verify task is back to pending
    pg_task = await store.get_task(pool, task.id)
    assert pg_task.status == TaskStatus.PENDING
    assert pg_task.assignee is None
    assert pg_task.claim_expires_at is None

    # Verify task is in the ready queue
    queue_key = channels.ready_queue(project)
    members = await redis_conn.zrange(queue_key, 0, -1)
    assert task.id in members


# ---------------------------------------------------------------------------
# Test 3: sweep does not release non-expired claims
# ---------------------------------------------------------------------------


@pytest.mark.asyncio
async def test_sweep_does_not_release_non_expired_claims(pool, redis_conn, project):
    """A task with a long TTL should not be released by sweep."""
    task = Task(id=gen_task_id(), project_id=project, title="Long TTL claim")
    task = await store.create_task(pool, task)
    task = await store.claim_task(pool, task.id, "agent-1", ttl_seconds=3600)

    assert task.status == TaskStatus.CLAIMED

    count = await sweep_expired_claims(pool, redis_conn, project)
    assert count == 0

    # Verify task is still claimed
    pg_task = await store.get_task(pool, task.id)
    assert pg_task.status == TaskStatus.CLAIMED
    assert pg_task.assignee == "agent-1"
