"""Event bus subscribers for github_webhooks domain.

Handles auto-merge re-evaluation for both task-completion and
feature-completion events, and posts PR comments when review feedback
tasks are completed.
"""

import logging
import re

import httpx

from peon_mcp.common.events import (
    EventType,
    FeatureCompletedEvent,
    TaskCompletedEvent,
    on,
)

logger = logging.getLogger(__name__)

_GITHUB_API_BASE = "https://api.github.com"
# Matches https://github.com/{owner}/{repo}/pull/{number}
_PR_URL_RE = re.compile(r"https://github\.com/([^/]+/[^/]+)/pull/(\d+)")


@on(EventType.TASK_COMPLETED)
async def check_feature_auto_merge(event: TaskCompletedEvent) -> None:
    """Re-evaluate auto-merge when all tasks in a feature are done."""
    if not event.task_data.get("all_feature_tasks_complete"):
        return

    feature_pr_url = event.task_data.get("feature_pr_url", "")
    if not feature_pr_url:
        return

    try:
        from peon_mcp.github_webhooks.auto_merge import auto_merge_handler

        await auto_merge_handler.re_evaluate_for_pr(feature_pr_url)
    except Exception as exc:
        logger.debug("Auto-merge re-evaluation failed (non-fatal): %s", exc)


@on(EventType.FEATURE_COMPLETED)
async def merge_completed_feature_pr(event: FeatureCompletedEvent) -> None:
    """Auto-merge the feature PR after feature completion."""
    if not event.pr_url or not event.project_path:
        return

    try:
        from peon_mcp.github import merge_feature_pr

        await merge_feature_pr(event.pr_url, event.project_path)
    except Exception as exc:
        logger.debug("Feature PR auto-merge failed (non-fatal): %s", exc)


@on(EventType.TASK_COMPLETED)
async def notify_pr_feedback_addressed(event: TaskCompletedEvent) -> None:
    """Post a PR comment when an 'Address PR review feedback' task is done.

    Only fires for review-type tasks whose title starts with
    "Address PR review feedback".  'Code review' tasks are excluded
    (those post their own review via gh pr review).
    """
    task_type = event.task_data.get("task_type", "")
    title = event.task_data.get("title", "")

    if task_type != "review":
        return
    if not title.startswith("Address PR review feedback"):
        return

    pr_url = event.pr_url or event.task_data.get("pr_url", "")
    if not pr_url:
        logger.debug("notify_pr_feedback_addressed: no pr_url on task %d; skipping", event.task_id)
        return

    match = _PR_URL_RE.match(pr_url)
    if not match:
        logger.warning(
            "notify_pr_feedback_addressed: cannot parse pr_url %r for task %d",
            pr_url, event.task_id,
        )
        return

    repo = match.group(1)
    pr_number = int(match.group(2))
    owner = repo.split("/")[0]

    try:
        from peon_mcp.github_webhooks.pr_reviewer import _api_headers, _get_token

        token = _get_token(owner=owner)
        if not token:
            logger.warning(
                "notify_pr_feedback_addressed: no GitHub App token for %s; skipping", owner
            )
            return
    except Exception as exc:
        logger.warning("notify_pr_feedback_addressed: failed to get token: %s", exc)
        return

    body = _build_feedback_comment(event)

    url = f"{_GITHUB_API_BASE}/repos/{repo}/issues/{pr_number}/comments"
    try:
        async with httpx.AsyncClient(timeout=15.0) as client:
            resp = await client.post(url, headers=_api_headers(token), json={"body": body})
        if resp.status_code not in (200, 201):
            logger.warning(
                "notify_pr_feedback_addressed: POST %s returned %d: %s",
                url, resp.status_code, resp.text[:300],
            )
        else:
            logger.info(
                "notify_pr_feedback_addressed: posted feedback-addressed comment on %s#%d",
                repo, pr_number,
            )
    except Exception as exc:
        logger.warning("notify_pr_feedback_addressed: failed to post comment: %s", exc)


def _build_feedback_comment(event: TaskCompletedEvent) -> str:
    """Build the markdown comment body for a completed feedback-address task."""
    lines_added = event.lines_added if event.lines_added is not None else 0
    lines_deleted = event.lines_deleted if event.lines_deleted is not None else 0

    parts = ["## Feedback Addressed\n\nReview feedback has been addressed and pushed to this branch.\n"]

    if event.work_log_summary:
        parts.append(f"\n**Summary**: {event.work_log_summary}")
    if event.work_log_files_changed:
        parts.append(f"\n**Files changed**: {event.work_log_files_changed}")
    parts.append(f"\n**Lines**: +{lines_added} / -{lines_deleted}")
    if event.work_log_test_result:
        parts.append(f"\n**Tests**: {event.work_log_test_result}")

    return "".join(parts)
