"""Tests for TimelineService."""

from datetime import datetime, timezone
from unittest.mock import AsyncMock

import pytest

from hangar.models.beads import BeadsTask, BeadsTaskList
from hangar.services.timeline import TimelineService


@pytest.fixture
def mock_beads_service() -> AsyncMock:
    """Create a mock BeadsService."""
    return AsyncMock()


@pytest.fixture
def service(mock_beads_service: AsyncMock) -> TimelineService:
    """Create a TimelineService with mocked BeadsService."""
    return TimelineService(beads_service=mock_beads_service)


def _make_task(
    id: str,
    title: str,
    status: str = "open",
    issue_type: str = "task",
    created_at: str | None = None,
    updated_at: str | None = None,
    closed_at: str | None = None,
    close_reason: str | None = None,
) -> BeadsTask:
    """Helper to create a BeadsTask."""
    return BeadsTask(
        id=id,
        title=title,
        status=status,
        issue_type=issue_type,
        created_at=created_at,
        updated_at=updated_at,
        closed_at=closed_at,
        close_reason=close_reason,
    )


@pytest.mark.asyncio
async def test_empty_timeline(service: TimelineService, mock_beads_service: AsyncMock) -> None:
    """Timeline with no tasks should return empty."""
    mock_beads_service.list_tasks.return_value = BeadsTaskList(tasks=[])
    result = await service.get_timeline()
    assert result.events == []
    assert result.total_events == 0


@pytest.mark.asyncio
async def test_created_events(service: TimelineService, mock_beads_service: AsyncMock) -> None:
    """Open tasks generate 'created' events."""
    mock_beads_service.list_tasks.return_value = BeadsTaskList(tasks=[
        _make_task("t1", "Task 1", "open", created_at="2026-02-07T10:00:00+01:00"),
        _make_task("t2", "Task 2", "open", created_at="2026-02-07T11:00:00+01:00"),
    ])
    result = await service.get_timeline()
    assert result.total_events == 2
    assert all(e.event_type == "created" for e in result.events)
    # Sorted newest first
    assert result.events[0].task_id == "t2"


@pytest.mark.asyncio
async def test_closed_events_include_reason(service: TimelineService, mock_beads_service: AsyncMock) -> None:
    """Closed tasks generate 'created' + 'closed' events with close_reason."""
    mock_beads_service.list_tasks.return_value = BeadsTaskList(tasks=[
        _make_task(
            "t1", "Task 1", "closed",
            created_at="2026-02-07T10:00:00+01:00",
            closed_at="2026-02-07T12:00:00+01:00",
            close_reason="Shipped it!",
        ),
    ])
    result = await service.get_timeline()
    # Should have created + closed events
    event_types = [e.event_type for e in result.events]
    assert "created" in event_types
    assert "closed" in event_types
    # Find the closed event
    closed = [e for e in result.events if e.event_type == "closed"][0]
    assert closed.close_reason == "Shipped it!"


@pytest.mark.asyncio
async def test_epics_filtered_out(service: TimelineService, mock_beads_service: AsyncMock) -> None:
    """Epic-type tasks should not generate timeline events."""
    mock_beads_service.list_tasks.return_value = BeadsTaskList(tasks=[
        _make_task("epic-1", "Epic 1", "open", issue_type="epic", created_at="2026-02-07T10:00:00+01:00"),
        _make_task("t1", "Task 1", "open", created_at="2026-02-07T11:00:00+01:00"),
    ])
    result = await service.get_timeline()
    assert result.total_events == 1
    assert result.events[0].task_id == "t1"


@pytest.mark.asyncio
async def test_events_sorted_newest_first(service: TimelineService, mock_beads_service: AsyncMock) -> None:
    """Events should be sorted newest-first by timestamp."""
    mock_beads_service.list_tasks.return_value = BeadsTaskList(tasks=[
        _make_task("t1", "First", "closed",
                   created_at="2026-02-07T10:00:00+01:00",
                   closed_at="2026-02-07T11:00:00+01:00"),
        _make_task("t2", "Second", "closed",
                   created_at="2026-02-07T12:00:00+01:00",
                   closed_at="2026-02-07T14:00:00+01:00"),
    ])
    result = await service.get_timeline()
    timestamps = [e.timestamp for e in result.events]
    assert timestamps == sorted(timestamps, reverse=True)
