"""Tests for escalation list/resolve (triage) functionality."""

from __future__ import annotations

import pytest

from loom.graph import store
from loom.graph.project import create_project
from loom.graph.task import Task, TaskStatus
from loom.ids import task_id as gen_task_id


@pytest.fixture
async def project(pool):
    record = await create_project(pool, "esc-triage-test", "Escalation triage tests")
    return str(record["id"])


@pytest.fixture
async def blocked_task(pool, project):
    task = Task(
        id=gen_task_id(), project_id=project, title="Blocked task",
        status=TaskStatus.BLOCKED,
    )
    return await store.create_task(pool, task)


@pytest.fixture
async def escalation(pool, project, blocked_task):
    esc_id = await store.create_escalation(
        pool, project, blocked_task.id, "Need human input on API design",
    )
    return esc_id


class TestListEscalations:
    async def test_list_open_escalations(self, pool, project, escalation):
        rows = await store.list_escalations(pool, project, resolved=False)
        assert len(rows) == 1
        assert rows[0]["id"] == escalation
        assert rows[0]["resolved"] is False
        assert rows[0]["task_title"] == "Blocked task"

    async def test_list_empty_when_no_escalations(self, pool, project):
        rows = await store.list_escalations(pool, project, resolved=False)
        assert rows == []

    async def test_list_resolved_escalations(self, pool, project, escalation):
        await store.resolve_escalation(pool, escalation)
        open_rows = await store.list_escalations(pool, project, resolved=False)
        resolved_rows = await store.list_escalations(pool, project, resolved=True)
        assert len(open_rows) == 0
        assert len(resolved_rows) == 1

    async def test_list_all_escalations(self, pool, project, blocked_task):
        esc1 = await store.create_escalation(pool, project, blocked_task.id, "First")
        esc2 = await store.create_escalation(pool, project, blocked_task.id, "Second")
        await store.resolve_escalation(pool, esc1)
        all_rows = await store.list_escalations(pool, project, resolved=None)
        assert len(all_rows) == 2

    async def test_list_respects_limit(self, pool, project, blocked_task):
        for i in range(5):
            await store.create_escalation(pool, project, blocked_task.id, f"Esc {i}")
        rows = await store.list_escalations(pool, project, resolved=False, limit=3)
        assert len(rows) == 3

    async def test_list_includes_task_status(self, pool, project, escalation, blocked_task):
        rows = await store.list_escalations(pool, project, resolved=False)
        assert rows[0]["task_status"] == "blocked"

    async def test_multiple_tasks_with_escalations(self, pool, project):
        t1 = Task(id=gen_task_id(), project_id=project, title="Task A", status=TaskStatus.BLOCKED)
        t2 = Task(id=gen_task_id(), project_id=project, title="Task B", status=TaskStatus.BLOCKED)
        await store.create_task(pool, t1)
        await store.create_task(pool, t2)
        await store.create_escalation(pool, project, t1.id, "Blocked on A")
        await store.create_escalation(pool, project, t2.id, "Blocked on B")
        rows = await store.list_escalations(pool, project, resolved=False)
        assert len(rows) == 2
        titles = {r["task_title"] for r in rows}
        assert titles == {"Task A", "Task B"}


class TestResolveEscalation:
    async def test_resolve_sets_resolved_flag(self, pool, project, escalation):
        row = await store.resolve_escalation(pool, escalation)
        assert row["resolved"] is True
        assert row["resolved_at"] is not None

    async def test_resolve_nonexistent_raises(self, pool):
        with pytest.raises(Exception):
            await store.resolve_escalation(pool, 999999)

    async def test_resolve_idempotent(self, pool, project, escalation):
        await store.resolve_escalation(pool, escalation)
        row = await store.resolve_escalation(pool, escalation)
        assert row["resolved"] is True
