#!/usr/bin/env python3
"""
AtomGit Pull Request Creation Tool

自动创建 PR,从当前分支生成 PR 标题和描述

用法:
    python3 pr_creation.py --branch <branch> --fork-owner <owner> [--title "标题"] [--dry-run]
"""

import os
import sys
import json
import argparse
import subprocess
from pathlib import Path
from typing import List, Dict, Optional
from atomgit_sdk import AtomGitClient, resolve_atomgit_context



def run_git(args: List[str], cwd: str = None) -> str:
    """运行 git 命令并返回输出"""
    result = subprocess.run(
        ["git"] + args, cwd=cwd or os.getcwd(), capture_output=True, text=True
    )
    if result.returncode != 0:
        raise Exception(f"Git 命令失败: {' '.join(args)}\n{result.stderr}")
    return result.stdout.strip()


def get_current_branch() -> str:
    """获取当前分支名"""
    return run_git(["rev-parse", "--abbrev-ref", "HEAD"])


def is_valid_branch_name(name: str) -> bool:
    """验证分支名是否有效"""
    if not name or name in ("master", "main", "HEAD"):
        return False
    try:
        run_git(["rev-parse", "--verify", name])
        return True
    except:
        return False


def get_best_base_ref(base_branch: str) -> str:
    """智能解析最佳基准引用,优先使用远程分支"""
    remotes = run_git(["remote"]).split()

    # 优先序: upstream -> origin -> local
    if "upstream" in remotes:
        return f"upstream/{base_branch}"
    if "origin" in remotes:
        return f"origin/{base_branch}"
    return base_branch


def get_commit_messages(branch: str, base_branch: str = "master") -> List[Dict]:
    """获取分支相对于基线的提交信息"""
    base_ref = get_best_base_ref(base_branch)
    log_format = "%H%n%s%n%b%n---COMMIT_END---"

    try:
        output = run_git(["log", f"{base_ref}..{branch}", f"--format={log_format}"])
    except:
        # 如果远程引用不存在,回退到本地
        output = run_git(["log", f"{base_branch}..{branch}", f"--format={log_format}"])

    commits = []
    for block in output.split("---COMMIT_END---"):
        if not block.strip():
            continue
        lines = block.strip().split("\n", 2)
        if len(lines) >= 2:
            commits.append(
                {
                    "hash": lines[0],
                    "subject": lines[1],
                    "body": lines[2] if len(lines) > 2 else "",
                }
            )

    return commits


def get_changed_files(branch: str, base_branch: str = "master") -> List[str]:
    """获取变更文件列表"""
    base_ref = get_best_base_ref(base_branch)
    try:
        output = run_git(["diff", "--name-only", f"{base_ref}...{branch}"])
    except:
        output = run_git(["diff", "--name-only", f"{base_branch}...{branch}"])
    return [f for f in output.split("\n") if f.strip()]


def get_diff_stats(branch: str, base_branch: str = "master") -> Dict:
    """获取 diff 统计信息"""
    base_ref = get_best_base_ref(base_branch)
    try:
        output = run_git(["diff", "--stat", f"{base_ref}...{branch}"])
    except:
        output = run_git(["diff", "--stat", f"{base_branch}...{branch}"])

    stats = {"files_changed": 0, "insertions": 0, "deletions": 0}

    for line in output.split("\n"):
        if "file" in line and "changed" in line:
            parts = line.split(",")
            for part in parts:
                part = part.strip()
                if "file" in part:
                    stats["files_changed"] = int(part.split()[0])
                elif "insertion" in part:
                    stats["insertions"] = int(part.split()[0])
                elif "deletion" in part:
                    stats["deletions"] = int(part.split()[0])

    return stats


def add_ai_signature(description: str, ai_model: str) -> str:
    """添加 AI 签名(单独一行, 与正文空一行)"""
    signature = f"\n\n---\n\n🤖 generated by ai@{ai_model}"
    if "generated by ai@" not in description:
        return description + signature
    return description


def load_config(config_path: str) -> dict:
    """加载配置文件"""
    with open(config_path, "r", encoding="utf-8") as f:
        config = json.load(f)

    if not config.get("atomgit") or not config["atomgit"].get("token"):
        raise Exception("配置文件中缺少 atomgit.token")

    return config


def main():
    parser = argparse.ArgumentParser(description="AtomGit PR 创建工具")
    parser.add_argument("--branch", type=str, help="源分支名")
    parser.add_argument("--base", type=str, default="master", help="目标分支名")
    parser.add_argument("--title", type=str, help="PR 标题")
    parser.add_argument("--body", type=str, help="PR 描述文本")
    parser.add_argument("--description-file", type=str, help="从文件读取 PR 描述 (Markdown 格式)")
    parser.add_argument("--config", type=str, default="config.json", help="配置文件路径")
    parser.add_argument("--owner", type=str, help="目标仓库 owner,覆盖 config.json")
    parser.add_argument("--repo", type=str, help="目标仓库 repo,覆盖 config.json")
    parser.add_argument(
        "--url",
        type=str,
        help="AtomGit/GitCode 仓库或 PR 链接,用于自动解析 owner/repo",
    )
    parser.add_argument(
        "--fork-owner",
        type=str,
        required=True,
        help="Fork 仓库的 owner(必需,通过 git remote -v 获取)",
    )
    parser.add_argument("--draft", action="store_true", help="创建为草稿 PR")
    parser.add_argument("--dry-run", action="store_true", help="仅显示计划,不实际创建")
    parser.add_argument("-y", "--yes", action="store_true", help="自动确认创建 PR")
    parser.add_argument(
        "--ai-model",
        type=str,
        default="ai",
        help="AI模型名称,用于签名 (默认: ai)",
    )
    args = parser.parse_args()

    try:
        sdk_config, parsed_url = resolve_atomgit_context(
            args.config, owner=args.owner, repo=args.repo, url=args.url
        )
    except Exception as e:
        print(f"❌ 加载配置失败: {e}")
        sys.exit(1)

    branch = args.branch or get_current_branch()

    if not is_valid_branch_name(branch):
        print(f"❌ 无效的分支名: {branch}")
        sys.exit(1)

    if branch in ("master", "main"):
        print("❌ 不能从 master/main 分支创建 PR")
        sys.exit(1)

    print("=" * 60)
    print("🚀 AtomGit PR Creator")
    print("=" * 60)
    print(f"源分支: {branch}")
    print(f"目标分支: {args.base}")
    print(f"目标仓库: {sdk_config.owner}/{sdk_config.repo}")
    print(f"Fork owner: {args.fork_owner}")
    if args.url:
        print(f"解析链接: {args.url}")
        if parsed_url.get("pr_number") is not None:
            print("ℹ️  已忽略链接中的 PR 编号,仅使用其中的仓库信息创建 PR")
        if parsed_url.get("issue_number") is not None:
            print("ℹ️  已忽略链接中的 Issue 编号,仅使用其中的仓库信息创建 PR")
    print()

    print(">>> 获取提交信息...")
    commits = get_commit_messages(branch, args.base)
    print(f"✓ 找到 {len(commits)} 个提交")

    if not commits:
        print(f"❌ 在 {args.base}{branch} 之间未找到提交")
        print("   请确保你的分支与 upstream/master 同步")
        sys.exit(1)

    print(">>> 获取变更文件...")
    files = get_changed_files(branch, args.base)
    print(f"✓ 找到 {len(files)} 个变更文件")

    print(">>> 计算变更统计...")
    stats = get_diff_stats(branch, args.base)
    print(
        f"✓ +{stats['insertions']}/-{stats['deletions']} 行, {stats['files_changed']} 文件"
    )

    print(">>> 生成 PR 描述...")
    
    # 描述优先级: --description-file > --body
    if args.description_file:
        try:
            with open(args.description_file, "r", encoding="utf-8") as f:
                description = f.read()
            print(f"✓ 从文件读取描述: {args.description_file}")
        except Exception as e:
            print(f"❌ 读取描述文件失败: {e}")
            sys.exit(1)
    elif args.body:
        description = args.body
    else:
        print("❌ 错误: 必须提供 PR 描述。")
        print("   建议先让 AI 分析变更并生成专业描述文件,然后使用 --description-file 参数。")
        print("   或者使用 --body 参数直接传入描述内容。")
        sys.exit(1)

    # 添加 AI 签名
    description = add_ai_signature(description, args.ai_model)

    title = args.title or commits[0]["subject"]
    print(f"✓ 标题: {title}")

    print()
    print("=" * 60)
    print("生成的 PR 描述:")
    print("=" * 60)
    print(description)
    print("=" * 60)
    print()

    if args.dry_run:
        print("⚠ Dry run 模式,未创建 PR")
        sys.exit(0)

    if args.yes:
        answer = "y"
    else:
        try:
            answer = input("\n是否创建 PR?(y/n): ").strip().lower()
        except:
            answer = "n"

    if answer in ("y", "yes"):
        print(">>> 创建 PR...")
        api = AtomGitClient(sdk_config)

        pr_head = f"{args.fork_owner}:{branch}"

        try:
            pr = api.create_pull_request(
                title=title,
                body=description,
                head=pr_head,
                base=args.base,
                draft=args.draft,
            )
            pr_number = pr.get("number")
            pr_url = api.get_pr_url(pr_number)

            print()
            print("✅ PR 创建成功!")
            print(f"PR 编号: #{pr_number}")
            print(f"PR 链接: {pr_url}")

        except Exception as e:
            print(f"❌ 创建 PR 失败: {e}")
            sys.exit(1)
    else:
        print(">>> 已取消创建 PR")
        sys.exit(0)


if __name__ == "__main__":
    main()