"""Upload benchmark results to the leaderboard via GitHub."""

from __future__ import annotations

import shutil
import subprocess
from pathlib import Path

from claw_bench.submission.packager import validate_package


def gh_available() -> bool:
    """Check whether the ``gh`` CLI tool is installed."""
    return shutil.which("gh") is not None


def submit_pr(results_dir: Path, repo: str, name: str) -> str:
    """Fork *repo*, create a branch, commit results, and open a PR.

    Uses the ``gh`` CLI tool for GitHub operations.
    Returns the URL of the created pull request.

    Raises:
        ValueError: If the results package is invalid.
        RuntimeError: If ``gh`` is not installed or a git operation fails.
        NotImplementedError: If ``gh`` is not available.
    """
    results_dir = Path(results_dir)
    if not validate_package(results_dir):
        raise ValueError(
            "Results package is invalid or missing manifest. "
            "Run package_results() first."
        )

    if not gh_available():
        raise NotImplementedError(
            "GitHub PR submission requires the 'gh' CLI tool. "
            "Install from https://cli.github.com/"
        )

    # Check gh auth status
    auth_check = subprocess.run(
        ["gh", "auth", "status"],
        capture_output=True,
        text=True,
        timeout=10,
    )
    if auth_check.returncode != 0:
        raise RuntimeError(
            "Not authenticated with GitHub. Run 'gh auth login' first."
        )

    # Fork the repo (idempotent)
    subprocess.run(
        ["gh", "repo", "fork", repo, "--clone=false"],
        capture_output=True,
        text=True,
        timeout=30,
    )

    # Clone the fork
    import tempfile
    work_dir = Path(tempfile.mkdtemp(prefix="claw-bench-submit-"))
    clone_result = subprocess.run(
        ["gh", "repo", "clone", repo, str(work_dir / "repo"), "--", "--depth=1"],
        capture_output=True,
        text=True,
        timeout=60,
    )
    if clone_result.returncode != 0:
        raise RuntimeError(f"Failed to clone repo: {clone_result.stderr}")

    repo_dir = work_dir / "repo"
    branch_name = f"submit/{name}"

    # Create branch
    subprocess.run(
        ["git", "checkout", "-b", branch_name],
        cwd=repo_dir,
        capture_output=True,
        timeout=10,
    )

    # Copy results into the repo
    import shutil as sh
    dest = repo_dir / "submissions" / name
    dest.mkdir(parents=True, exist_ok=True)
    for f in results_dir.rglob("*"):
        if f.is_file():
            rel = f.relative_to(results_dir)
            target = dest / rel
            target.parent.mkdir(parents=True, exist_ok=True)
            sh.copy2(f, target)

    # Commit
    subprocess.run(["git", "add", "."], cwd=repo_dir, capture_output=True, timeout=10)
    subprocess.run(
        ["git", "commit", "-m", f"Add benchmark results: {name}"],
        cwd=repo_dir,
        capture_output=True,
        timeout=10,
    )

    # Push and create PR
    subprocess.run(
        ["git", "push", "-u", "origin", branch_name],
        cwd=repo_dir,
        capture_output=True,
        timeout=30,
    )

    pr_result = subprocess.run(
        [
            "gh", "pr", "create",
            "--title", f"Benchmark submission: {name}",
            "--body", f"Automated benchmark result submission for **{name}**.\n\nGenerated by `claw-bench submit`.",
            "--repo", repo,
        ],
        cwd=repo_dir,
        capture_output=True,
        text=True,
        timeout=30,
    )
    if pr_result.returncode != 0:
        raise RuntimeError(f"Failed to create PR: {pr_result.stderr}")

    # Clean up work dir
    sh.rmtree(work_dir, ignore_errors=True)

    return pr_result.stdout.strip()


def submit_dry_run(results_dir: Path) -> None:
    """Validate the package and print what *submit_pr* would do."""
    results_dir = Path(results_dir)
    is_valid = validate_package(results_dir)

    print(f"Results directory: {results_dir}")
    print(f"Package valid:     {is_valid}")

    if not is_valid:
        print("ERROR: package validation failed; fix before submitting.")
        return

    files = sorted(
        str(p.relative_to(results_dir))
        for p in results_dir.rglob("*")
        if p.is_file()
    )
    print(f"Files to upload:   {len(files)}")
    for f in files:
        print(f"  - {f}")
    print(f"\nGitHub CLI:        {'available' if gh_available() else 'NOT FOUND'}")
    print("Dry run complete. No changes were made.")
