"""Tests for the status-terminal consolidation trigger in update_note."""
from unittest.mock import AsyncMock, MagicMock, patch


def _mock_session_for_update(mock_note):
    mock_session = AsyncMock()
    mock_result = MagicMock()
    mock_result.scalars.return_value.first.return_value = mock_note
    mock_session.execute = AsyncMock(return_value=mock_result)
    mock_session.commit = AsyncMock()
    mock_session.refresh = AsyncMock()
    mock_session.__aenter__ = AsyncMock(return_value=mock_session)
    mock_session.__aexit__ = AsyncMock(return_value=False)
    return mock_session


async def test_update_note_to_done_triggers_consolidation():
    """status: in_progress → done should fire maybe_consolidate(task_closed)."""
    mock_note = MagicMock()
    mock_note.id = 42
    mock_note.status = "in_progress"   # pre-update state
    mock_note.body = ""
    mock_note.title = ""
    mock_note.tags = []
    mock_note.started_at = None
    mock_note.completed_at = None
    mock_note.recurrence_rule = None
    mock_note.project_id = None

    with patch(
        "fabledassistant.services.notes.async_session",
        return_value=_mock_session_for_update(mock_note),
    ), patch(
        "fabledassistant.services.consolidation.maybe_consolidate",
        new=AsyncMock(),
    ) as mock_mc:
        from fabledassistant.services.notes import update_note
        await update_note(1, 42, status="done")

    mock_mc.assert_awaited_once_with(1, 42, reason="task_closed")


async def test_update_note_to_cancelled_triggers_consolidation():
    mock_note = MagicMock()
    mock_note.id = 42
    mock_note.status = "in_progress"
    mock_note.body = ""
    mock_note.title = ""
    mock_note.tags = []
    mock_note.started_at = None
    mock_note.completed_at = None
    mock_note.recurrence_rule = None
    mock_note.project_id = None

    with patch(
        "fabledassistant.services.notes.async_session",
        return_value=_mock_session_for_update(mock_note),
    ), patch(
        "fabledassistant.services.consolidation.maybe_consolidate",
        new=AsyncMock(),
    ) as mock_mc:
        from fabledassistant.services.notes import update_note
        await update_note(1, 42, status="cancelled")

    mock_mc.assert_awaited_once_with(1, 42, reason="task_closed")


async def test_update_note_to_in_progress_does_not_trigger_consolidation():
    """Non-terminal status changes don't fire the trigger."""
    mock_note = MagicMock()
    mock_note.id = 42
    mock_note.status = "todo"
    mock_note.body = ""
    mock_note.title = ""
    mock_note.tags = []
    mock_note.started_at = None
    mock_note.completed_at = None
    mock_note.recurrence_rule = None
    mock_note.project_id = None

    with patch(
        "fabledassistant.services.notes.async_session",
        return_value=_mock_session_for_update(mock_note),
    ), patch(
        "fabledassistant.services.consolidation.maybe_consolidate",
        new=AsyncMock(),
    ) as mock_mc:
        from fabledassistant.services.notes import update_note
        await update_note(1, 42, status="in_progress")

    mock_mc.assert_not_awaited()


async def test_update_note_already_done_does_not_retrigger():
    """If the status was already 'done' and update_note(status='done') runs
    again, no fresh trigger fires — only transitions count."""
    mock_note = MagicMock()
    mock_note.id = 42
    mock_note.status = "done"
    mock_note.body = ""
    mock_note.title = ""
    mock_note.tags = []
    mock_note.started_at = None
    mock_note.completed_at = None
    mock_note.recurrence_rule = None
    mock_note.project_id = None

    with patch(
        "fabledassistant.services.notes.async_session",
        return_value=_mock_session_for_update(mock_note),
    ), patch(
        "fabledassistant.services.consolidation.maybe_consolidate",
        new=AsyncMock(),
    ) as mock_mc:
        from fabledassistant.services.notes import update_note
        await update_note(1, 42, status="done")

    mock_mc.assert_not_awaited()
