#!/usr/bin/env bash
# Prepare a release for human approval.
#
# This script does everything an agent can do to prepare a release,
# stopping at the point where human action is required (merging PR, signing tag).
#
# Usage:
#   ./scripts/prepare-release VERSION [--dry-run] [--no-pr]
#
# Arguments:
#   VERSION      Version to release (e.g., 0.8.0)
#   --dry-run    Show what would happen without making changes
#   --no-pr      Skip PR creation (just prepare locally)
#
# What this script does:
#   1. Bumps version in pyproject.toml and __init__.py
#   2. Updates CHANGELOG.md (Unreleased → new version)
#   3. Commits the changes
#   4. Runs release-check validations
#   5. Creates PR from dev → main
#   6. Outputs handoff instructions for human
#
# What the human must do after:
#   1. Review and merge the PR on Codeberg
#   2. Run: ./scripts/tag-release VERSION
#
set -euo pipefail

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m'

DRY_RUN=false
NO_PR=false
VERSION=""

# Parse arguments
while [[ $# -gt 0 ]]; do
    case $1 in
        --dry-run)
            DRY_RUN=true
            shift
            ;;
        --no-pr)
            NO_PR=true
            shift
            ;;
        -h|--help)
            echo "Usage: $0 VERSION [--dry-run] [--no-pr]"
            echo ""
            echo "Prepares a release for human approval."
            echo ""
            echo "Arguments:"
            echo "  VERSION      Version to release (e.g., 0.8.0)"
            echo "  --dry-run    Show what would happen without making changes"
            echo "  --no-pr      Skip PR creation (just prepare locally)"
            exit 0
            ;;
        -*)
            echo "Unknown option: $1"
            exit 1
            ;;
        *)
            VERSION="$1"
            shift
            ;;
    esac
done

if [[ -z "$VERSION" ]]; then
    echo -e "${RED}Error: VERSION is required${NC}"
    echo "Usage: $0 VERSION [--dry-run] [--no-pr]"
    exit 1
fi

# Validate version format
if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]; then
    echo -e "${RED}Error: Invalid version format: $VERSION${NC}"
    echo "Expected: MAJOR.MINOR.PATCH or MAJOR.MINOR.PATCH-suffix"
    exit 1
fi

# Get project root
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
cd "$PROJECT_ROOT"

echo "╔════════════════════════════════════════╗"
echo "║     Prepare Release v$VERSION"
echo "╚════════════════════════════════════════╝"
echo ""

if $DRY_RUN; then
    echo -e "${YELLOW}[DRY RUN MODE - no changes will be made]${NC}"
    echo ""
fi

run() {
    if $DRY_RUN; then
        echo -e "${BLUE}[dry-run]${NC} $*"
    else
        "$@"
    fi
}

# ─────────────────────────────────────────────────────────────
echo "━━━ Step 1: Pre-flight checks ━━━"
# ─────────────────────────────────────────────────────────────

# Check we're on dev branch
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
if [[ "$CURRENT_BRANCH" != "dev" ]]; then
    echo -e "${RED}Error: Must be on 'dev' branch (currently on '$CURRENT_BRANCH')${NC}"
    echo "Run: git checkout dev"
    exit 1
fi
echo -e "${GREEN}✓${NC} On dev branch"

# Check for uncommitted changes
if [[ -n "$(git status --porcelain)" ]]; then
    echo -e "${RED}Error: Uncommitted changes detected${NC}"
    git status --short
    echo "Commit or stash changes before preparing release."
    exit 1
fi
echo -e "${GREEN}✓${NC} Working directory clean"

# Sync with remote
echo "  Syncing with remote..."
run git fetch origin
run git pull origin dev

# Check tag doesn't already exist
if git rev-parse "v$VERSION" >/dev/null 2>&1; then
    echo -e "${RED}Error: Tag v$VERSION already exists${NC}"
    exit 1
fi
echo -e "${GREEN}✓${NC} Tag v$VERSION is available"

# ─────────────────────────────────────────────────────────────
echo ""
echo "━━━ Step 2: Bump version ━━━"
# ─────────────────────────────────────────────────────────────

CURRENT_VERSION=$(grep -E '^version\s*=' pyproject.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')
echo "Current version: $CURRENT_VERSION"
echo "New version: $VERSION"

if ! $DRY_RUN; then
    # Update pyproject.toml
    sed -i "s/^version = \"$CURRENT_VERSION\"/version = \"$VERSION\"/" pyproject.toml
    echo -e "${GREEN}✓${NC} Updated pyproject.toml"

    # Update __init__.py
    INIT_FILE="src/hypergumbo/__init__.py"
    if [[ -f "$INIT_FILE" ]] && grep -q "__version__" "$INIT_FILE"; then
        sed -i "s/__version__ = \"$CURRENT_VERSION\"/__version__ = \"$VERSION\"/" "$INIT_FILE"
        echo -e "${GREEN}✓${NC} Updated $INIT_FILE"
    fi
else
    echo -e "${BLUE}[dry-run]${NC} Would update pyproject.toml: $CURRENT_VERSION → $VERSION"
    echo -e "${BLUE}[dry-run]${NC} Would update src/hypergumbo/__init__.py"
fi

# ─────────────────────────────────────────────────────────────
echo ""
echo "━━━ Step 3: Update CHANGELOG ━━━"
# ─────────────────────────────────────────────────────────────

TODAY=$(date +%Y-%m-%d)

if grep -q "## \[Unreleased\]" CHANGELOG.md; then
    if ! $DRY_RUN; then
        # Insert new version header after [Unreleased]
        # This keeps [Unreleased] for future changes and adds the version below it
        sed -i "s/## \[Unreleased\]/## [Unreleased]\n\n## [$VERSION] - $TODAY/" CHANGELOG.md

        # Update the header line that shows released version
        sed -i "s/^- Released \*\*tool\*\* is at: v[0-9.]*$/- Released **tool** is at: v$VERSION/" CHANGELOG.md

        echo -e "${GREEN}✓${NC} Updated CHANGELOG.md with [$VERSION] - $TODAY"
    else
        echo -e "${BLUE}[dry-run]${NC} Would update CHANGELOG.md: [Unreleased] → [$VERSION] - $TODAY"
    fi
else
    echo -e "${YELLOW}!${NC} CHANGELOG.md has no [Unreleased] section"
fi

# ─────────────────────────────────────────────────────────────
echo ""
echo "━━━ Step 4: Commit changes ━━━"
# ─────────────────────────────────────────────────────────────

if ! $DRY_RUN; then
    git add pyproject.toml src/hypergumbo/__init__.py CHANGELOG.md
    git commit -s -m "chore: release $VERSION"
    echo -e "${GREEN}✓${NC} Committed: chore: release $VERSION"
else
    echo -e "${BLUE}[dry-run]${NC} Would commit: chore: release $VERSION"
fi

# ─────────────────────────────────────────────────────────────
echo ""
echo "━━━ Step 5: Run release checks ━━━"
# ─────────────────────────────────────────────────────────────

if ! $DRY_RUN; then
    if ./scripts/release-check; then
        echo -e "${GREEN}✓${NC} All release checks passed"
    else
        echo -e "${RED}✗${NC} Release checks failed"
        echo ""
        echo "Options:"
        echo "  1. Fix issues and run: git commit --amend"
        echo "  2. Reset: git reset --hard HEAD~1"
        exit 1
    fi
else
    echo -e "${BLUE}[dry-run]${NC} Would run ./scripts/release-check"
fi

# ─────────────────────────────────────────────────────────────
echo ""
echo "━━━ Step 6: Push to dev ━━━"
# ─────────────────────────────────────────────────────────────

if ! $DRY_RUN; then
    git push origin dev
    echo -e "${GREEN}✓${NC} Pushed to origin/dev"
else
    echo -e "${BLUE}[dry-run]${NC} Would push to origin/dev"
fi

# ─────────────────────────────────────────────────────────────
echo ""
echo "━━━ Step 7: Create PR to main ━━━"
# ─────────────────────────────────────────────────────────────

if $NO_PR; then
    echo -e "${YELLOW}Skipping PR creation (--no-pr)${NC}"
    PR_URL="(not created)"
else
    if ! $DRY_RUN; then
        # Create PR using Codeberg's refs/for/ syntax
        PR_OUTPUT=$(git push origin "dev:refs/for/main/release-$VERSION" \
            -o title="Release v$VERSION" \
            -o description="Merge dev into main for v$VERSION release.

## Checklist for reviewer
- [ ] Version bumped correctly
- [ ] CHANGELOG updated
- [ ] CI passes" 2>&1) || true

        # Extract PR URL from output (Codeberg outputs it)
        PR_URL=$(echo "$PR_OUTPUT" | grep -oE 'https://[^ ]+/pulls/[0-9]+' | head -1 || echo "")

        if [[ -n "$PR_URL" ]]; then
            echo -e "${GREEN}✓${NC} PR created: $PR_URL"
        else
            echo -e "${GREEN}✓${NC} PR branch pushed (check Codeberg for PR)"
            PR_URL="(check Codeberg)"
        fi
    else
        echo -e "${BLUE}[dry-run]${NC} Would create PR: dev → main"
        PR_URL="(dry-run)"
    fi
fi

# ─────────────────────────────────────────────────────────────
echo ""
echo "╔════════════════════════════════════════════════════════════╗"
echo -e "║  ${GREEN}Release v$VERSION prepared!${NC}                              "
echo "╚════════════════════════════════════════════════════════════╝"
echo ""
echo -e "${CYAN}═══ HANDOFF TO HUMAN ═══${NC}"
echo ""
echo "The agent has completed all automated preparation steps."
echo "A human must now complete the release:"
echo ""
echo "  1. Review and merge the PR on Codeberg"
if [[ -n "$PR_URL" && "$PR_URL" != "(not created)" && "$PR_URL" != "(dry-run)" ]]; then
    echo "     $PR_URL"
fi
echo ""
echo "  2. After PR is merged, run:"
echo -e "     ${GREEN}./scripts/tag-release $VERSION${NC}"
echo ""
echo "  This will create a signed tag and push it, triggering the"
echo "  release workflow that publishes to PyPI and Codeberg releases."
echo ""
