"""Service for computing aggregate project statistics from beads task data."""

from hangar.models.beads import BeadsTask
from hangar.models.stats import EpicStats, ProjectStats
from hangar.services.beads import BeadsService


class StatsService:
    """Computes project statistics from beads task data."""

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

    def _compute_stats(self, tasks: list[BeadsTask]) -> ProjectStats:
        """Compute aggregate statistics from a list of tasks."""
        if not tasks:
            return ProjectStats()

        total = len(tasks)
        closed = sum(1 for t in tasks if t.status == "closed")
        in_progress = sum(1 for t in tasks if t.status == "in_progress")
        open_count = sum(1 for t in tasks if t.status == "open")

        # Completion rate
        completion_rate = (closed / total * 100) if total > 0 else 0.0

        # Time span
        created_dates = [t.created_at for t in tasks if t.created_at]
        closed_dates = [t.closed_at for t in tasks if t.closed_at]

        first_created = min(created_dates) if created_dates else None
        last_closed = max(closed_dates) if closed_dates else None

        time_span_days: float | None = None
        if first_created and last_closed:
            delta = last_closed - first_created
            time_span_days = delta.total_seconds() / 86400

        # Average lead time (created → closed for closed tasks)
        lead_times: list[float] = []
        for task in tasks:
            if task.status == "closed" and task.created_at and task.closed_at:
                delta = task.closed_at - task.created_at
                lead_times.append(delta.total_seconds() / 3600)  # hours

        avg_lead_time = sum(lead_times) / len(lead_times) if lead_times else None

        # Throughput (tasks closed per day)
        throughput: float | None = None
        if time_span_days and time_span_days > 0 and closed > 0:
            throughput = closed / time_span_days

        return ProjectStats(
            total_tasks=total,
            closed_tasks=closed,
            in_progress_tasks=in_progress,
            open_tasks=open_count,
            completion_rate=round(completion_rate, 1),
            avg_lead_time_hours=round(avg_lead_time, 1) if avg_lead_time is not None else None,
            time_span_days=round(time_span_days, 1) if time_span_days is not None else None,
            first_task_created=first_created,
            last_task_closed=last_closed,
            throughput_per_day=round(throughput, 2) if throughput is not None else None,
        )

    def _compute_epic_stats(self, all_tasks: list[BeadsTask]) -> list[EpicStats]:
        """Compute per-epic statistics."""
        # Group tasks by parent epic using the dependency chain
        # Epic tasks have issue_type="epic", child tasks depend on them
        epics = [t for t in all_tasks if t.issue_type == "epic"]
        regular_tasks = [t for t in all_tasks if t.issue_type == "task"]

        epic_stats: list[EpicStats] = []

        for epic in epics:
            # Find child tasks that depend on this epic
            epic_children = [
                t for t in regular_tasks
                if any(
                    d.depends_on_id == epic.id or d.issue_id == epic.id
                    for d in t.dependencies
                )
            ]

            if not epic_children:
                # Also check if the task ID starts with the epic ID (e.g., hangar-ku7.1 → hangar-ku7)
                epic_children = [
                    t for t in regular_tasks
                    if t.id.startswith(epic.id + ".")
                ]

            closed_count = sum(1 for t in epic_children if t.status == "closed")

            created_dates = [t.created_at for t in epic_children if t.created_at]
            closed_dates = [t.closed_at for t in epic_children if t.closed_at]

            first_created = min(created_dates) if created_dates else None
            last_closed = max(closed_dates) if closed_dates else None

            time_span: float | None = None
            if first_created and last_closed:
                delta = last_closed - first_created
                time_span = round(delta.total_seconds() / 86400, 1)

            epic_stats.append(
                EpicStats(
                    epic_id=epic.id,
                    epic_title=epic.title,
                    task_count=len(epic_children),
                    closed_count=closed_count,
                    time_span_days=time_span,
                    first_created=first_created,
                    last_closed=last_closed,
                    close_reason=epic.close_reason,
                )
            )

        return epic_stats

    async def get_stats(self) -> ProjectStats:
        """Compute full project statistics from beads task data."""
        task_list = await self.beads_service.list_tasks()

        # Compute aggregate stats from tasks only (not epics)
        tasks_only = [t for t in task_list.tasks if t.issue_type == "task"]
        stats = self._compute_stats(tasks_only)

        # Compute per-epic stats
        stats.epic_stats = self._compute_epic_stats(task_list.tasks)

        return stats
