"""PullRequestService — automated PR creation for task completion.

Generates PR title/body from task metadata and delegates actual
GitHub API calls to ``GitHubClient``.

Design decisions:
- PR body includes task summary, changed files list, and branch info.
- Operates independently of DB — receives data as parameters.
- Falls back gracefully when GitHubClient is not configured.
"""

from __future__ import annotations

from dataclasses import dataclass, field

import structlog

from kgn.github.client import GitHubClient

log = structlog.get_logger("kgn.github.pr")

# GitHub API limit for PR body length
_MAX_PR_BODY_LENGTH = 65_536
_TRUNCATION_NOTICE = "\n\n---\n⚠️ *Body truncated (exceeded 65536 char limit)*"


@dataclass
class PRResult:
    """Result of a PR creation attempt."""

    success: bool
    pr_number: int | None = None
    html_url: str | None = None
    message: str = ""


@dataclass
class PRContext:
    """Context for creating a task-completion PR.

    All information needed to build a PR, passed by the caller
    to avoid coupling PullRequestService to DB models.
    """

    task_title: str
    task_id: str
    branch_name: str
    base_branch: str = "main"
    agent_key: str = ""
    changed_files: list[str] = field(default_factory=list)
    node_summary: str = ""


class PullRequestService:
    """Automated PR creation and listing for KGN task workflows.

    PR title: ``kgn: complete TASK <title>``
    PR body: Markdown with task info, changed files, and branch info.
    """

    def __init__(self, github_client: GitHubClient) -> None:
        self._github = github_client

    def create_task_pr(self, ctx: PRContext) -> PRResult:
        """Create a PR for a completed task.

        Args:
            ctx: PR context with task metadata and changed files.

        Returns:
            PRResult with PR number and URL on success.
        """
        title = f"kgn: complete TASK {ctx.task_title}"
        body = self._build_pr_body(ctx)

        # R-025: Truncate body if it exceeds GitHub API limit (65536 chars)
        if len(body) > _MAX_PR_BODY_LENGTH:
            cut = _MAX_PR_BODY_LENGTH - len(_TRUNCATION_NOTICE)
            body = body[:cut] + _TRUNCATION_NOTICE

        try:
            response = self._github.create_pull_request(
                title=title,
                head=ctx.branch_name,
                base=ctx.base_branch,
                body=body,
            )
            pr_number = response.get("number")
            html_url = response.get("html_url", "")

            log.info(
                "pr.created",
                pr_number=pr_number,
                branch=ctx.branch_name,
                task=ctx.task_title,
            )

            return PRResult(
                success=True,
                pr_number=pr_number,
                html_url=html_url,
                message=f"PR #{pr_number} created",
            )

        except Exception as exc:
            log.error("pr.create_failed", error=str(exc), branch=ctx.branch_name)
            return PRResult(
                success=False,
                message=f"PR creation failed: {exc}",
            )

    def list_prs(self, state: str = "open") -> list[dict]:
        """List Pull Requests from the configured repository.

        Args:
            state: Filter by PR state (``open``, ``closed``, ``all``).

        Returns:
            List of PR dicts from GitHub API.
        """
        return self._github.list_pull_requests(state=state)

    @staticmethod
    def _build_pr_body(ctx: PRContext) -> str:
        """Build Markdown body for a task-completion PR."""
        lines: list[str] = []

        lines.append(f"## Task: {ctx.task_title}")
        lines.append("")
        lines.append(f"- **Task ID**: `{ctx.task_id}`")
        lines.append(f"- **Agent**: `{ctx.agent_key}`")
        lines.append(f"- **Branch**: `{ctx.branch_name}`")

        if ctx.node_summary:
            lines.append("")
            lines.append("### Summary")
            lines.append(ctx.node_summary)

        if ctx.changed_files:
            lines.append("")
            lines.append("### Changed Files")
            for f in ctx.changed_files:
                lines.append(f"- `{f}`")

        lines.append("")
        lines.append("---")
        lines.append("*Auto-generated by KGN*")

        return "\n".join(lines)
