#!/usr/bin/env bash
set -euo pipefail

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

usage() {
    echo "Usage: script/release [--major | --minor | --patch]"
    echo ""
    echo "Increments the version number, creates a release PR,"
    echo "and after merge, tags and publishes the release."
    echo ""
    echo "Options:"
    echo "  --major    Bump major version (x.0.0)"
    echo "  --minor    Bump minor version (0.x.0)"
    echo "  --patch    Bump patch version (0.0.x)"
    echo "  --dry-run  Show what would happen without making changes"
    echo "  --help     Show this help message"
    exit 1
}

log() { echo -e "${GREEN}==>${NC} $1"; }
info() { echo -e "${BLUE}   ${NC} $1"; }
warn() { echo -e "${YELLOW}warning:${NC} $1"; }
error() { echo -e "${RED}error:${NC} $1" >&2; exit 1; }

BUMP_TYPE=""
DRY_RUN=false

while [[ $# -gt 0 ]]; do
    case $1 in
        --major) BUMP_TYPE="major"; shift ;;
        --minor) BUMP_TYPE="minor"; shift ;;
        --patch) BUMP_TYPE="patch"; shift ;;
        --dry-run) DRY_RUN=true; shift ;;
        --help|-h) usage ;;
        *) error "Unknown option: $1" ;;
    esac
done

[[ -z "$BUMP_TYPE" ]] && error "Must specify --major, --minor, or --patch"
[[ ! -f "Cargo.toml" ]] && error "Must run from repository root"

if [[ -n "$(git status --porcelain)" ]]; then
    error "Working directory is not clean. Commit or stash changes first."
fi

CURRENT_BRANCH=$(git branch --show-current)
[[ "$CURRENT_BRANCH" != "main" ]] && error "Must be on main branch (currently on $CURRENT_BRANCH)"

git fetch origin main
LOCAL=$(git rev-parse HEAD)
REMOTE=$(git rev-parse origin/main)
[[ "$LOCAL" != "$REMOTE" ]] && error "Local main is not up to date with origin. Run 'git pull' first."

CURRENT_VERSION=$(grep '^version = ' Cargo.toml | head -1 | sed 's/version = "\(.*\)"/\1/')
[[ -z "$CURRENT_VERSION" ]] && error "Could not read version from Cargo.toml"

log "Current version: $CURRENT_VERSION"

IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT_VERSION"

case $BUMP_TYPE in
    major) MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0 ;;
    minor) MINOR=$((MINOR + 1)); PATCH=0 ;;
    patch) PATCH=$((PATCH + 1)) ;;
esac

NEW_VERSION="${MAJOR}.${MINOR}.${PATCH}"
RELEASE_BRANCH="release/v${NEW_VERSION}"

log "New version: $NEW_VERSION"

if $DRY_RUN; then
    log "[dry-run] Would create branch: $RELEASE_BRANCH"
    log "[dry-run] Would update Cargo.toml, src/shell.rs, Cargo.lock"
    log "[dry-run] Would create PR for release"
    log "[dry-run] After PR merge, would tag v$NEW_VERSION"
    log "[dry-run] Would create GitHub release"
    log "[dry-run] Would publish to crates.io"
    exit 0
fi

# Create release branch
log "Creating release branch..."
git checkout -b "$RELEASE_BRANCH"

# Update versions
log "Updating Cargo.toml..."
sed -i '' "s/^version = \"$CURRENT_VERSION\"/version = \"$NEW_VERSION\"/" Cargo.toml

log "Updating src/shell.rs..."
sed -i '' "s/spool shell v$CURRENT_VERSION/spool shell v$NEW_VERSION/" src/shell.rs

log "Updating Cargo.lock..."
cargo update --package spool --quiet

# Run tests
log "Running tests..."
cargo test --quiet

log "Running clippy..."
cargo clippy --quiet -- -D warnings

# Commit and push
log "Committing changes..."
git add Cargo.toml Cargo.lock src/shell.rs
git commit -m "Release v$NEW_VERSION"

log "Pushing release branch..."
git push -u origin "$RELEASE_BRANCH"

# Create PR
log "Creating release PR..."
PR_URL=$(gh pr create \
    --title "Release v$NEW_VERSION" \
    --body "## Release v$NEW_VERSION

Bumps version from $CURRENT_VERSION to $NEW_VERSION.

### Changes
- Updated version in Cargo.toml
- Updated version in src/shell.rs
- Updated Cargo.lock

### After merge
Run \`script/release-tag $NEW_VERSION\` to:
- Create git tag v$NEW_VERSION
- Create GitHub release
- Publish to crates.io" \
    --head "$RELEASE_BRANCH" \
    --base main)

echo ""
log "Release PR created: $PR_URL"
echo ""
info "Next steps:"
info "1. Review and merge the PR"
info "2. Run: script/release-tag $NEW_VERSION"
