"""Core scorecard service — orchestrates scorecard generation."""

from __future__ import annotations

from datetime import datetime

from dashboard.services.scorecard.aggregators import (
    aggregate_metrics,
    collect_events_for_period,
    ensure_all_tracked_agents,
    query_token_transactions,
)
from dashboard.services.scorecard.calculators import detect_patterns
from dashboard.services.scorecard.formatters import generate_narrative_bullets
from dashboard.services.scorecard.types import (
    TRACKED_AGENTS,
    AgentMetrics,
    PeriodType,
    ScorecardSummary,
)
from dashboard.services.scorecard.validators import get_period_bounds


def generate_scorecard(
    agent_id: str,
    period_type: PeriodType = PeriodType.daily,
    reference_date: datetime | None = None,
) -> ScorecardSummary | None:
    """Generate a scorecard for a single agent.

    Args:
        agent_id: The agent to generate scorecard for
        period_type: daily or weekly
        reference_date: The date to calculate from (defaults to now)

    Returns:
        ScorecardSummary or None if agent has no activity
    """
    start, end = get_period_bounds(period_type, reference_date)

    # Collect events
    events = collect_events_for_period(start, end, agent_id)

    # Aggregate metrics
    all_metrics = aggregate_metrics(events)

    # Get metrics for this specific agent
    if agent_id not in all_metrics:
        # Create empty metrics - still generate a scorecard
        metrics = AgentMetrics(agent_id=agent_id)
    else:
        metrics = all_metrics[agent_id]

    # Augment with token data from ledger
    tokens_earned, tokens_spent = query_token_transactions(agent_id, start, end)
    metrics.tokens_earned = max(metrics.tokens_earned, tokens_earned)
    metrics.tokens_spent = max(metrics.tokens_spent, tokens_spent)

    # Generate narrative and patterns
    narrative = generate_narrative_bullets(metrics, period_type)
    patterns = detect_patterns(metrics)

    return ScorecardSummary(
        agent_id=agent_id,
        period_type=period_type,
        period_start=start,
        period_end=end,
        metrics=metrics,
        narrative_bullets=narrative,
        patterns=patterns,
    )


def generate_all_scorecards(
    period_type: PeriodType = PeriodType.daily,
    reference_date: datetime | None = None,
) -> list[ScorecardSummary]:
    """Generate scorecards for all tracked agents.

    Args:
        period_type: daily or weekly
        reference_date: The date to calculate from (defaults to now)

    Returns:
        List of ScorecardSummary for all agents with activity
    """
    start, end = get_period_bounds(period_type, reference_date)

    # Collect all events
    events = collect_events_for_period(start, end)

    # Aggregate metrics for all agents
    all_metrics = aggregate_metrics(events)

    # Include tracked agents even if no activity
    ensure_all_tracked_agents(all_metrics)

    # Generate scorecards
    scorecards: list[ScorecardSummary] = []

    for agent_id, metrics in all_metrics.items():
        # Augment with token data
        tokens_earned, tokens_spent = query_token_transactions(agent_id, start, end)
        metrics.tokens_earned = max(metrics.tokens_earned, tokens_earned)
        metrics.tokens_spent = max(metrics.tokens_spent, tokens_spent)

        narrative = generate_narrative_bullets(metrics, period_type)
        patterns = detect_patterns(metrics)

        scorecard = ScorecardSummary(
            agent_id=agent_id,
            period_type=period_type,
            period_start=start,
            period_end=end,
            metrics=metrics,
            narrative_bullets=narrative,
            patterns=patterns,
        )
        scorecards.append(scorecard)

    # Sort by agent_id for consistent ordering
    scorecards.sort(key=lambda s: s.agent_id)

    return scorecards


def get_tracked_agents() -> list[str]:
    """Return the list of tracked agent IDs."""
    return sorted(TRACKED_AGENTS)
