"""Handler for pull_request.closed (unmerged) GitHub webhook events.

Registers a handler on the module-level dispatcher singleton. Import this
module to activate the handler — it self-registers on import.

On PR closed without merge:
  1. Logs the closure with context (who closed, time open, last commit).
  2. Marks any linked Peon tasks as 'closed'.
"""

from __future__ import annotations

import logging

from peon_mcp.db import get_pool
from peon_mcp.github_webhooks.dispatcher import register_handler

logger = logging.getLogger(__name__)


@register_handler("pull_request")
async def handle_pr_closed_unmerged(delivery_id: str, payload: dict) -> None:
    """Revert linked tasks when a PR is closed without merging."""
    action = payload.get("action")
    pr = payload.get("pull_request", {})

    # Only act on closed-without-merge events.
    if action != "closed" or pr.get("merged", False):
        return

    pr_url = pr.get("html_url", "")
    pr_number = pr.get("number", 0)
    pr_title = pr.get("title", "")
    repo = payload.get("repository", {}).get("full_name", "unknown")

    closer = pr.get("closed_by") or {}
    closed_by = closer.get("login", "unknown") if isinstance(closer, dict) else "unknown"
    created_at = pr.get("created_at", "")
    closed_at = pr.get("closed_at", "")
    commits = pr.get("commits", 0)
    changed_files = pr.get("changed_files", 0)

    logger.info(
        "PR closed without merge: #%d '%s' in %s — closed by %s "
        "(opened: %s, closed: %s, commits: %d, files: %d)",
        pr_number,
        pr_title,
        repo,
        closed_by,
        created_at,
        closed_at,
        commits,
        changed_files,
    )

    if not pr_url:
        logger.info("PR closed handler: no html_url in payload, skipping DB updates")
        return

    pool = get_pool()
    async with pool.acquire() as conn:
        await _close_tasks(conn, pr_url, pr_number)


async def _close_tasks(conn, pr_url: str, pr_number: int) -> None:
    """Mark tasks linked to the closed (unmerged) PR as 'closed'."""
    rows = await conn.fetch(
        "SELECT id, project_id, status FROM tasks WHERE pr_url = $1",
        pr_url,
    )

    task_ids: list[int] = []
    for row in rows:
        task_id = row["id"]
        project_id = row["project_id"]
        old_status = row["status"]

        if old_status in ("done", "cancelled", "merged", "closed"):
            logger.debug(
                "PR closed: skipping task #%d (status=%s, already terminal)",
                task_id,
                old_status,
            )
            continue

        task_ids.append(task_id)
        await conn.execute(
            "UPDATE tasks SET status = 'closed', updated_at = CURRENT_TIMESTAMP"
            " WHERE id = $1",
            task_id,
        )
        logger.info(
            "PR closed (#%d): marked task #%d (project=%s) as 'closed' (was '%s')",
            pr_number,
            task_id,
            project_id,
            old_status,
        )

    logger.info(
        "PR closed handler: PR #%d processed, %d task(s) marked closed",
        pr_number,
        len(task_ids),
    )
