"""Service for constructing a chronological project timeline from beads task data."""

from hangar.models.beads import BeadsTask, BeadsTaskList
from hangar.models.timeline import EpicGroup, TimelineEvent, TimelineResponse
from hangar.services.beads import BeadsService


class TimelineService:
    """Constructs chronological events from beads task data."""

    def __init__(self, beads_service: BeadsService) -> None:
        self.beads_service = beads_service

    def _build_events(self, tasks: list[BeadsTask]) -> list[TimelineEvent]:
        """Build timeline events from task lifecycle timestamps."""
        events: list[TimelineEvent] = []

        for task in tasks:
            # Find parent epic from dependencies (parent-child type)
            epic_id: str | None = None
            epic_title: str | None = None

            # Created event
            if task.created_at:
                events.append(
                    TimelineEvent(
                        event_type="created",
                        task_id=task.id,
                        task_title=task.title,
                        timestamp=task.created_at,
                        epic_id=epic_id,
                        epic_title=epic_title,
                    )
                )

            # Claimed event (status changed to in_progress — use updated_at if status is in_progress or closed)
            # We approximate "claimed" as the updated_at when it differs from created_at
            # and the task has been at least in_progress
            if (
                task.status in ("in_progress", "closed")
                and task.updated_at
                and task.created_at
                and task.updated_at != task.created_at
                and (task.closed_at is None or task.updated_at != task.closed_at)
            ):
                events.append(
                    TimelineEvent(
                        event_type="claimed",
                        task_id=task.id,
                        task_title=task.title,
                        timestamp=task.updated_at,
                        epic_id=epic_id,
                        epic_title=epic_title,
                    )
                )

            # Closed event
            if task.status == "closed" and task.closed_at:
                events.append(
                    TimelineEvent(
                        event_type="closed",
                        task_id=task.id,
                        task_title=task.title,
                        timestamp=task.closed_at,
                        close_reason=task.close_reason,
                        epic_id=epic_id,
                        epic_title=epic_title,
                    )
                )

        # Sort newest first
        events.sort(key=lambda e: e.timestamp, reverse=True)
        return events

    def _group_by_epic(self, events: list[TimelineEvent]) -> list[EpicGroup]:
        """Group events by their parent epic."""
        epic_map: dict[str, EpicGroup] = {}

        for event in events:
            if event.epic_id:
                if event.epic_id not in epic_map:
                    epic_map[event.epic_id] = EpicGroup(
                        epic_id=event.epic_id,
                        epic_title=event.epic_title or event.epic_id,
                        task_count=0,
                        events=[],
                    )
                group = epic_map[event.epic_id]
                group.events.append(event)
                # Count unique tasks
                task_ids = {e.task_id for e in group.events}
                group.task_count = len(task_ids)

        return list(epic_map.values())

    async def get_timeline(self) -> TimelineResponse:
        """Build the full project timeline from beads task data."""
        task_list = await self.beads_service.list_tasks()

        # Filter out epics — we want task-level events
        tasks = [t for t in task_list.tasks if t.issue_type == "task"]

        events = self._build_events(tasks)
        epic_groups = self._group_by_epic(events)

        return TimelineResponse(
            events=events,
            epic_groups=epic_groups,
            total_events=len(events),
        )
