#!/usr/bin/env python3
"""
PR comment management for release previews.

This script creates or updates PR comments with release preview information
when changes are detected in the monorepo using the GitHub CLI (gh).

Usage:
  python scripts/pr_comment.py [--pr-number PR_NUMBER]

Environment Variables:
  GITHUB_TOKEN - GitHub token for API access (used by gh CLI)
  GH_REPO - Repository in format owner/repo (used by gh CLI)
  PR_NUMBER - Pull request number
"""

import argparse
import json
import os
import subprocess
import sys
import tempfile
from pathlib import Path


def run_command(cmd: list[str], cwd: str | None = None) -> tuple[int, str, str]:
    """Run a command and return exit code, stdout, stderr."""
    try:
        result = subprocess.run(
            cmd, capture_output=True, text=True, cwd=cwd
        )
        return result.returncode, result.stdout.strip(), result.stderr.strip()
    except Exception as e:
        return 1, "", str(e)


def check_gh_cli() -> bool:
    """Check if gh CLI is available."""
    exit_code, _, _ = run_command(["gh", "--version"])
    return exit_code == 0


def get_existing_comment_id(pr_number: int) -> str | None:
    """Find existing release preview comment ID using gh CLI."""
    cmd = ["gh", "pr", "view", str(pr_number), "--json", "comments"]

    exit_code, stdout, stderr = run_command(cmd)

    if exit_code != 0:
        print(f"Warning: Failed to get PR comments: {stderr}")
        return None

    try:
        pr_data = json.loads(stdout)
        comments = pr_data.get("comments", [])

        # Look for comments with our signature
        signature = "This comment was automatically generated by the release preview workflow"

        for comment in comments:
            comment_body = comment.get("body", "")
            # Also check for release preview header as backup
            if (signature in comment_body or
                "📦 Release Preview" in comment_body):
                # Use databaseId (numeric) instead of id (GraphQL node ID) for REST API
                comment_id = comment.get("databaseId") or comment.get("id")
                if comment_id:
                    print(f"Found existing comment with ID: {comment_id} (type: {type(comment_id)})")
                    return str(comment_id)

        print("No existing release preview comment found")
        return None
    except json.JSONDecodeError as e:
        print(f"Warning: Failed to parse PR comments JSON: {e}")
        return None


def get_release_preview() -> str:
    """Get the release preview using the version preview script."""
    exit_code, stdout, stderr = run_command([
        "uv", "run", "python", "scripts/version_preview.py", "--format", "github-summary"
    ])

    if exit_code != 0:
        raise Exception(f"Failed to get release preview: {stderr}")

    return stdout


def get_changelog_preview() -> str:
    """Get the changelog preview using just command."""
    exit_code, stdout, stderr = run_command([
        "just", "preview-changelog"
    ])

    if exit_code != 0:
        raise Exception(f"Failed to get changelog preview: {stderr}")

    return stdout


def has_changes() -> bool:
    """Check if there are any packages with changes."""
    exit_code, stdout, stderr = run_command([
        "uv", "run", "python", "scripts/version_preview.py", "--format", "json"
    ])

    if exit_code != 0:
        return False

    try:
        changes = json.loads(stdout)
        return len(changes) > 0
    except json.JSONDecodeError:
        return False


def create_comment_body() -> str:
    """Create the full comment body with release preview and changelog."""
    release_preview = get_release_preview()
    changelog_preview = get_changelog_preview()

    return f"""{release_preview}

### 📝 Changelog Preview

```
{changelog_preview}
```

---
*This comment was automatically generated by the release preview workflow.*"""


def create_or_update_comment(pr_number: int, comment_body: str) -> None:
    """Create a new comment or update existing one using gh CLI."""
    if not check_gh_cli():
        raise Exception("gh CLI is not available. Please install GitHub CLI.")

    # Get repository info from environment
    repo = os.environ.get("GH_REPO") or os.environ.get("GITHUB_REPOSITORY")
    if not repo:
        raise Exception("Repository not specified. Set GH_REPO or GITHUB_REPOSITORY environment variable.")

    # Create temporary file with comment body
    with tempfile.NamedTemporaryFile(mode='w', suffix='.md', delete=False) as f:
        f.write(comment_body)
        temp_file = f.name

    try:
        # Check if we have an existing comment to update
        existing_comment_id = get_existing_comment_id(pr_number)

        if existing_comment_id:
            print(f"Found existing comment {existing_comment_id}, attempting to update...")
            print(f"Using repository: {repo}")

            # Try to update existing comment using gh api
            cmd = ["gh", "api", f"repos/{repo}/issues/comments/{existing_comment_id}",
                   "--method", "PATCH", "--field", f"body=@{temp_file}"]

            exit_code, stdout, stderr = run_command(cmd)

            if exit_code != 0:
                print(f"Failed to update existing comment (it may have been deleted): {stderr}")
                print("Creating new comment instead...")

                # Fall back to creating a new comment
                cmd = ["gh", "pr", "comment", str(pr_number), "--body-file", temp_file]
                exit_code, stdout, stderr = run_command(cmd)

                if exit_code != 0:
                    raise Exception(f"Failed to create comment: {stderr}")

                print("Created new comment")
            else:
                print(f"Updated existing comment {existing_comment_id}")
        else:
            # Create new comment using gh pr comment
            print("No existing comment found, creating new comment...")
            cmd = ["gh", "pr", "comment", str(pr_number), "--body-file", temp_file]

            exit_code, stdout, stderr = run_command(cmd)

            if exit_code != 0:
                raise Exception(f"Failed to create comment: {stderr}")

            print("Created new comment")
    finally:
        # Clean up temporary file
        try:
            Path(temp_file).unlink()
        except Exception:
            pass  # Ignore cleanup errors


def main():
    """Main function with argument parsing."""
    parser = argparse.ArgumentParser(
        description="Create or update PR comment with release preview"
    )
    parser.add_argument(
        "--pr-number",
        type=int,
        help="Pull request number (can also use PR_NUMBER env var)"
    )

    args = parser.parse_args()

    # Get configuration from args or environment
    pr_number = args.pr_number or os.getenv("PR_NUMBER")

    if not pr_number:
        print("Error: PR number not provided via --pr-number or PR_NUMBER env var", file=sys.stderr)
        sys.exit(1)

    try:
        # Check if there are any changes
        if not has_changes():
            print("No changes detected, skipping PR comment")
            return

        # Create comment body
        comment_body = create_comment_body()

        # Create or update comment
        create_or_update_comment(int(pr_number), comment_body)

    except Exception as e:
        print(f"Error: {e}", file=sys.stderr)
        sys.exit(1)


if __name__ == "__main__":
    main()
