"""GitHub PR feedback — posts pipeline status to GitHub PRs for external contributors.

Three touchpoints:
1. Discovery ack: when pipeline discovers a mirrored PR
2. Eval review: when evaluation completes (approved or rejected with reasoning)
3. Merge/close outcome: when PR is merged or permanently closed

Only fires for PRs with a github_pr link (set by sync-mirror.sh).
All calls are non-fatal — GitHub feedback never blocks the pipeline.
"""

import logging
import os

import aiohttp

from . import config

logger = logging.getLogger("pipeline.github_feedback")

GITHUB_API = "https://api.github.com"
GITHUB_REPO = "living-ip/teleo-codex"

_BOT_ACCOUNTS = frozenset({"m3taversal", "teleo-bot", "teleo", "github-actions[bot]"})


def _github_pat() -> str | None:
    pat_file = config.SECRETS_DIR / "github-pat"
    if pat_file.exists():
        return pat_file.read_text().strip()
    return os.environ.get("GITHUB_PAT")


async def _post_comment(github_pr: int, body: str) -> bool:
    pat = _github_pat()
    if not pat:
        logger.warning("No GitHub PAT — skipping feedback for GH PR #%d", github_pr)
        return False

    url = f"{GITHUB_API}/repos/{GITHUB_REPO}/issues/{github_pr}/comments"
    headers = {
        "Authorization": f"Bearer {pat}",
        "Accept": "application/vnd.github+json",
        "X-GitHub-Api-Version": "2022-11-28",
    }

    try:
        async with aiohttp.ClientSession() as session:
            async with session.post(
                url, headers=headers, json={"body": body},
                timeout=aiohttp.ClientTimeout(total=30),
            ) as resp:
                if resp.status >= 400:
                    text = await resp.text()
                    logger.error("GitHub comment on PR #%d failed: %d %s", github_pr, resp.status, text[:200])
                    return False
                logger.info("GitHub comment posted on PR #%d", github_pr)
                return True
    except Exception:
        logger.exception("GitHub comment on PR #%d failed", github_pr)
        return False


async def _close_github_pr(github_pr: int) -> bool:
    pat = _github_pat()
    if not pat:
        return False

    url = f"{GITHUB_API}/repos/{GITHUB_REPO}/pulls/{github_pr}"
    headers = {
        "Authorization": f"Bearer {pat}",
        "Accept": "application/vnd.github+json",
        "X-GitHub-Api-Version": "2022-11-28",
    }

    try:
        async with aiohttp.ClientSession() as session:
            async with session.patch(
                url, headers=headers, json={"state": "closed"},
                timeout=aiohttp.ClientTimeout(total=30),
            ) as resp:
                if resp.status >= 400:
                    text = await resp.text()
                    logger.error("GitHub close PR #%d failed: %d %s", github_pr, resp.status, text[:200])
                    return False
                logger.info("GitHub PR #%d closed", github_pr)
                return True
    except Exception:
        logger.exception("GitHub close PR #%d failed", github_pr)
        return False


def _get_github_pr(conn, forgejo_pr: int) -> int | None:
    row = conn.execute(
        "SELECT github_pr FROM prs WHERE number = ? AND github_pr IS NOT NULL",
        (forgejo_pr,),
    ).fetchone()
    return row["github_pr"] if row else None


async def on_discovery(conn, forgejo_pr: int):
    """Post discovery acknowledgment to GitHub PR."""
    gh_pr = _get_github_pr(conn, forgejo_pr)
    if not gh_pr:
        return

    body = (
        "Your contribution has been received by the Teleo evaluation pipeline. "
        "It's queued for automated review (priority: high).\n\n"
        "You'll receive updates here as it progresses through evaluation.\n\n"
        "_Automated message from the [LivingIP](https://livingip.xyz) pipeline._"
    )
    await _post_comment(gh_pr, body)


async def on_eval_complete(conn, forgejo_pr: int, *, outcome: str, review_text: str = None, issues: list[str] = None):
    """Post evaluation result to GitHub PR.

    outcome: 'approved', 'rejected', 'changes_requested'
    """
    gh_pr = _get_github_pr(conn, forgejo_pr)
    if not gh_pr:
        return

    if outcome == "approved":
        body = "**Evaluation: Approved**\n\nYour contribution passed automated review and is queued for merge."
        if review_text:
            safe_text = review_text[:3000].replace("</details>", "&lt;/details&gt;")
            body += f"\n\n<details>\n<summary>Review details</summary>\n\n{safe_text}\n\n</details>"
    elif outcome == "rejected":
        body = "**Evaluation: Changes Requested**\n\n"
        if issues:
            body += "Issues found:\n"
            for issue in issues:
                body += f"- {issue}\n"
        if review_text:
            safe_text = review_text[:3000].replace("</details>", "&lt;/details&gt;")
            body += f"\n<details>\n<summary>Full review</summary>\n\n{safe_text}\n\n</details>"
        body += (
            "\n\nThe pipeline will attempt automated fixes where possible. "
            "If fixes fail, the PR will be closed — you're welcome to resubmit."
        )
    else:
        body = f"**Evaluation: {outcome}**\n\n"
        if review_text:
            body += review_text[:3000]

    body += "\n\n_Automated message from the [LivingIP](https://livingip.xyz) pipeline._"
    await _post_comment(gh_pr, body)


async def on_merged(conn, forgejo_pr: int, *, claims_count: int = None):
    """Post merge confirmation and close GitHub PR."""
    gh_pr = _get_github_pr(conn, forgejo_pr)
    if not gh_pr:
        return

    body = "**Merged!** Your contribution has been merged into the knowledge base."
    if claims_count and claims_count > 0:
        body += f" ({claims_count} claim{'s' if claims_count != 1 else ''} added)"
    body += (
        "\n\nThank you for contributing to LivingIP. "
        "Your attribution has been recorded.\n\n"
        "_Automated message from the [LivingIP](https://livingip.xyz) pipeline._"
    )
    await _post_comment(gh_pr, body)
    await _close_github_pr(gh_pr)


async def on_closed(conn, forgejo_pr: int, *, reason: str = None):
    """Post closure notification and close GitHub PR."""
    gh_pr = _get_github_pr(conn, forgejo_pr)
    if not gh_pr:
        return

    body = "**Closed.** "
    if reason:
        body += reason
    else:
        body += "This PR was closed after evaluation."
    body += (
        "\n\nYou're welcome to resubmit with changes. "
        "See the evaluation feedback above for guidance.\n\n"
        "_Automated message from the [LivingIP](https://livingip.xyz) pipeline._"
    )
    await _post_comment(gh_pr, body)
    await _close_github_pr(gh_pr)
