"""Tests for progress aggregation across claimed tasks."""

from __future__ import annotations

import pytest

from loom.graph import cache, store
from loom.graph.query import aggregate_progress
from loom.graph.task import Task, TaskStatus


@pytest.fixture
async def claimed_tasks(pool, project):
    """Create and claim three tasks."""
    tasks = []
    for i in range(3):
        t = Task(
            id=f"loom-prog-{i}",
            project_id=project,
            title=f"Task {i}",
            status=TaskStatus.PENDING,
        )
        created = await store.create_task(pool, t)
        claimed = await store.claim_task(pool, created.id, f"agent-{i}")
        tasks.append(claimed)
    return tasks


@pytest.mark.asyncio
async def test_no_claimed_tasks(pool, redis_conn, project):
    """Empty result when no tasks are claimed."""
    result = await aggregate_progress(pool, redis_conn, project)
    assert result["claimed_count"] == 0
    assert result["tasks"] == []
    assert result["average_percent"] is None


@pytest.mark.asyncio
async def test_claimed_without_progress(pool, redis_conn, project, claimed_tasks):
    """Claimed tasks without heartbeat progress still appear."""
    result = await aggregate_progress(pool, redis_conn, project)
    assert result["claimed_count"] == 3
    assert result["reporting_progress"] == 0
    assert result["average_percent"] is None
    assert len(result["tasks"]) == 3


@pytest.mark.asyncio
async def test_with_progress_data(pool, redis_conn, project, claimed_tasks):
    """Tasks with heartbeat progress report percent and message."""
    await cache.set_task_progress(redis_conn, project, "loom-prog-0", "Building", 25)
    await cache.set_task_progress(redis_conn, project, "loom-prog-1", "Testing", 75)
    result = await aggregate_progress(pool, redis_conn, project)
    assert result["claimed_count"] == 3
    assert result["reporting_progress"] == 2
    assert result["average_percent"] == 50  # (25 + 75) / 2
    # Check individual tasks have progress
    by_id = {t["id"]: t for t in result["tasks"]}
    assert by_id["loom-prog-0"]["progress"]["percent"] == 25
    assert by_id["loom-prog-0"]["progress"]["message"] == "Building"
    assert by_id["loom-prog-1"]["progress"]["percent"] == 75
    assert "progress" not in by_id["loom-prog-2"]


@pytest.mark.asyncio
async def test_all_at_100(pool, redis_conn, project, claimed_tasks):
    """All tasks at 100% reports average of 100."""
    for t in claimed_tasks:
        await cache.set_task_progress(redis_conn, project, t.id, "Done", 100)
    result = await aggregate_progress(pool, redis_conn, project)
    assert result["average_percent"] == 100
    assert result["reporting_progress"] == 3


@pytest.mark.asyncio
async def test_includes_assignee_and_priority(pool, redis_conn, project, claimed_tasks):
    """Each task entry includes assignee and priority."""
    result = await aggregate_progress(pool, redis_conn, project)
    for task in result["tasks"]:
        assert "assignee" in task
        assert "priority" in task
