"""Summary Workflow

Generates a summary of changes in a PR/MR.
"""

from __future__ import annotations

import time
from collections.abc import Callable
from pathlib import Path
from typing import Annotated

import jinja2
from pydantic import BaseModel, Field

from ..adaptors.issue import IssueHandler
from ..adaptors.repository import RepositoryHandler
from ..agents import (
    IssueExplorerAgent,
    OutputParserAgent,
    SummarizerAgent,
    SummaryParserAgent,
    TokenUsage,
)
from ..config import Config, Platform
from ..schema import Issue, MergeRequest
from ..utils import format_diff_with_line_numbers
from .context import PipelineContext
from .logging import WorkflowLogger

logger = WorkflowLogger("summary")


class SummaryResult(BaseModel):
    """Final result from the summary workflow"""

    merge_request: Annotated[
        MergeRequest, Field(description="The merge request that was summarized")
    ]
    summary_body: Annotated[str, Field(description="Formatted summary body")]
    total_usage: Annotated[TokenUsage, Field(description="Total token usage across all agents")]


class SummaryWorkflow:
    """Orchestrates the summary generation workflow.

    Usage:
        # For local/benchmark use (no platform I/O):
        workflow = SummaryWorkflow(config)
        result = await workflow.run(merge_request)

        # For full platform integration:
        result = await run_summary_workflow(config, repository, issue_handler, repo, merge_id)
    """

    def __init__(self, config: Config):
        """Initialize the workflow with agent configuration.

        Args:
            config: Configuration instance for creating agents
        """
        self.config = config

        # Initialize agents
        self.output_parser = OutputParserAgent(config=config.create_agent_config("output_parser"))
        self.issue_explorer = IssueExplorerAgent(
            config=config.create_agent_config("issue_explorer")
        )
        self.summarizer = SummarizerAgent(config=config.create_agent_config("summarizer"))
        self.summary_parser = SummaryParserAgent(
            config=config.create_agent_config("summary_parser")
        )

    async def run(
        self,
        merge_request: MergeRequest,
        issue_handler: IssueHandler | None = None,
        on_status: Callable[[str], None] | None = None,
        on_step_done: Callable[[str], None] | None = None,
    ) -> SummaryResult:
        """Run summary agents on a merge request and return results.

        This is the core summary logic without platform I/O (fetching/posting).
        Use run_summary_workflow() for the full orchestration with platform integration.

        Args:
            merge_request: The merge request to summarize (with diffs)
            issue_handler: For fetching linked issues (optional, skips if None)

        Returns:
            SummaryResult with summary and metrics
        """
        start_time = time.time()
        logger.info(f"Starting summary workflow for {merge_request.repo}#{merge_request.id}")

        try:
            # Initialize pipeline context
            ctx = PipelineContext(
                repo=merge_request.repo,
                merge_id=merge_request.id,
                platform=Platform.GITHUB,  # Summary workflow is platform-agnostic
            )

            ctx.merge_request = merge_request
            ctx.on_status = on_status
            ctx.on_step_done = on_step_done

            # Run agents
            if ctx.on_status:
                ctx.on_status("Exploring linked issues...")
            await self.issue_explorer.run(ctx, issue_handler, self.output_parser)
            if ctx.on_step_done:
                n = len(ctx.issues)
                ctx.on_step_done(f"{n} found" if n else "none")

            if ctx.on_status:
                ctx.on_status("Summarizing changes...")
            await self.summarizer.run(ctx, self.output_parser)

            if ctx.on_status:
                ctx.on_status("Formatting summary...")
            await self.summary_parser.run(ctx, self.output_parser)

            # Format summary
            assert ctx.parsed_summary is not None
            ctx.summary_body = format_summary_template(
                description=ctx.parsed_summary.description,
                issues=ctx.issues,
            )

            total_duration = time.time() - start_time
            logger.info(
                f"Summary workflow completed in {total_duration:.2f}s: "
                f"{ctx.total_usage.total_tokens} tokens"
            )

            return SummaryResult(
                merge_request=ctx.merge_request,
                summary_body=ctx.summary_body,
                total_usage=ctx.total_usage,
            )

        except Exception as e:
            logger.error("Workflow failed", type=type(e).__name__, message=str(e))
            raise


async def run_summary_workflow(
    config: Config,
    repository: RepositoryHandler,
    issue_handler: IssueHandler,
    repo: str,
    merge_id: str,
    dry_run: bool = False,
    on_status: Callable[[str], None] | None = None,
    on_step_done: Callable[[str], None] | None = None,
) -> SummaryResult:
    """Full workflow: fetch data, run summary agents, optionally post results.

    This is the main entry point for platform-integrated summaries.

    Args:
        config: Configuration instance
        repository: Repository handler for MRs
        issue_handler: Issue handler for fetching issues
        repo: Repository identifier (e.g., "owner/repo")
        merge_id: Merge request ID
        dry_run: Skip posting summary to platform

    Returns:
        SummaryResult with summary and metrics
    """
    start_time = time.time()
    logger.info(f"Starting summary workflow for {repo}#{merge_id}")

    # Fetch merge request
    merge_request = await repository.fetch_merge_request(repo, merge_id)
    merge_request.diffs = format_diff_with_line_numbers(merge_request.diffs)

    # Run the summary workflow
    workflow = SummaryWorkflow(config)
    result = await workflow.run(
        merge_request=merge_request,
        issue_handler=issue_handler,
        on_status=on_status,
        on_step_done=on_step_done,
    )

    # Post summary to platform
    if dry_run:
        logger.info("Dry run: skipping post of summary")
    else:
        logger.info("Posting summary")
        await repository.post_comment(
            repo=repo,
            merge_id=merge_id,
            content=result.summary_body,
        )

    total_duration = time.time() - start_time
    logger.info(f"Full summary workflow completed in {total_duration:.2f}s")

    return result


def format_summary_template(description: str, issues: list[Issue]) -> str:
    """Format the summary template with summary data.

    Args:
        description: Technical description of the changes
        issues: List of linked issues

    Returns:
        Formatted summary string
    """
    template_path = Path(__file__).parent.parent / "prompts" / "summary_template.txt"
    with open(template_path) as f:
        template_str = f.read()

    template = jinja2.Template(template_str)

    return template.render(
        description=description,
        issues=[issue.web_url for issue in issues],
    )
