"""Pipeline Context for workflow execution.

Shared state passed through the pipeline. Agents read and modify this context.
"""

from __future__ import annotations

from collections.abc import Callable
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Any, Literal, TypedDict

from ..agents import TokenUsage
from ..config import Platform
from ..utils import aggregate_token_usage

if TYPE_CHECKING:
    from ..adaptors.issue import Issue
    from ..adaptors.issue.schema import IssueSummary
    from ..agents.triage import ReasoningConfig
    from ..explorer import CodeExplorer
    from ..schema import MergeRequest, ParsedSummaryOutput, ReviewOutput, SummaryOutput

# Type aliases
PlatformReviewType = "GitHubReviewComment | GitLabReviewComment"
ReasoningEffort = Literal["low", "medium", "high"] | None


class LinkedRepoInfo(TypedDict):
    """Information about a linked repository for prompt rendering."""

    provider: str
    provider_url: str
    repo_path: str
    branch: str | None
    display_name: str | None
    name: str  # Short identifier used in namespaced paths [name]/...


class ImplicitGuidelineInfo(TypedDict):
    """Information about an implicit guideline for prompt rendering."""

    rule: str
    category: str
    action: str
    confidence: float
    domain: str | None


class TeamGuidelinesInfo(TypedDict):
    """Information about team guidelines for prompt rendering."""

    guidelines_text: str  # Natural language guidelines from LLM summarization
    feedback_count: int  # Number of feedbacks that contributed


@dataclass
class PipelineContext:
    """Shared context passed through the workflow pipeline.

    Agents read what they need and write their results back.
    """

    # Input (set at workflow start)
    repo: str
    merge_id: str
    platform: Platform
    debug: bool = False

    # Platform-specific response model
    response_model: type[ReviewOutput[Any]] | None = None

    # Accumulated state (agents modify these)
    merge_request: MergeRequest | None = None
    user_guidelines: str = ""
    issues: list[Issue] = field(default_factory=list)
    issue_summary: IssueSummary | None = None
    code_explorer: CodeExplorer | None = None
    reviews: list[Any] = field(default_factory=list)  # Platform-specific review type
    reasoning_effort: ReasoningEffort = None
    reasoning_config: ReasoningConfig | None = None  # Per-agent reasoning from triage

    # Linked repositories for cross-repo code exploration
    linked_repos: list[LinkedRepoInfo] = field(default_factory=list)

    # Implicit guidelines learned from user feedback (legacy - individual rules)
    implicit_guidelines: list[ImplicitGuidelineInfo] = field(default_factory=list)

    # Team guidelines (simplified - natural language from batch LLM summarization)
    team_guidelines: str | None = None

    # Platform-specific output format instructions (from handler.output_format())
    platform_output_format: str = ""

    # Summary workflow state
    summary: SummaryOutput | None = None
    parsed_summary: ParsedSummaryOutput | None = None
    summary_body: str = ""

    # Status callbacks (for CLI spinner updates)
    on_status: Callable[[str], None] | None = None
    on_step_done: Callable[[str], None] | None = None

    # Token tracking
    total_usage: TokenUsage = field(
        default_factory=lambda: TokenUsage(
            input_tokens=0, output_tokens=0, total_tokens=0, cached_tokens=0, model="aggregate"
        )
    )
    per_agent_usage: dict[str, dict] = field(default_factory=dict)

    def track(self, agent_name: str, usage: TokenUsage) -> None:
        """Track token usage from an agent."""
        self.total_usage = aggregate_token_usage(self.total_usage, usage)
        self.per_agent_usage[agent_name] = usage.model_dump()
