#!/bin/bash
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0

# Create Release Tag and GitHub Release for Python SDK
#
# Usage:
#   ./bin/create_release <VERSION> [PR_NUMBER]
#   ./bin/create_release <VERSION> --notes "Release notes text"
#   ./bin/create_release <VERSION> --notes-file path/to/notes.md
#
# Examples:
#   ./bin/create_release 0.5.0 4417           # Use PR #4417's description
#   ./bin/create_release 0.5.0                # Auto-find merged PR for this version
#   ./bin/create_release 0.5.0rc1 --notes "RC1 for 0.5.0"  # Release candidate, no PR
#   ./bin/create_release 0.5.0rc1 --notes-file rc-notes.md
#
# This script will:
#   1. Verify you're on main branch with latest changes
#   2. Fetch release notes (from PR or --notes/--notes-file)
#   3. Create an annotated git tag (py/v<VERSION>)
#   4. Push the tag to origin
#   5. Create a GitHub release

set -euo pipefail

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# Parse arguments
VERSION=""
PR_NUMBER=""
NOTES_STRING=""
NOTES_FILE=""

while [[ $# -gt 0 ]]; do
    case "$1" in
        --notes)
            if [[ -z "${2:-}" || "$2" == -* ]]; then
                echo -e "${RED}Error: --notes requires a value.${NC}"
                exit 1
            fi
            NOTES_STRING="$2"
            shift 2
            ;;
        --notes-file)
            if [[ -z "${2:-}" || "$2" == -* ]]; then
                echo -e "${RED}Error: --notes-file requires a value.${NC}"
                exit 1
            fi
            NOTES_FILE="$2"
            shift 2
            ;;
        -h|--help)
            echo "Usage: $0 <VERSION> [PR_NUMBER]"
            echo "       $0 <VERSION> --notes \"...\""
            echo "       $0 <VERSION> --notes-file path/to/notes.md"
            echo ""
            echo "Options:"
            echo "  --notes TEXT      Use this text as release notes (skips PR lookup)"
            echo "  --notes-file F   Use file contents as release notes (skips PR lookup)"
            exit 0
            ;;
        *)
            if [ -z "$VERSION" ]; then
                VERSION="$1"
            elif [ -z "$PR_NUMBER" ] && [[ "$1" =~ ^[0-9]+$ ]]; then
                PR_NUMBER="$1"
            else
                echo -e "${RED}Error: Unexpected argument: $1${NC}"
                exit 1
            fi
            shift
            ;;
    esac
done

if [ -z "$VERSION" ]; then
    echo -e "${RED}Usage: $0 <VERSION> [PR_NUMBER]${NC}"
    echo "       $0 <VERSION> --notes \"...\""
    echo "       $0 <VERSION> --notes-file path/to/notes.md"
    exit 1
fi

# Can't use both notes options
if [ -n "$NOTES_STRING" ] && [ -n "$NOTES_FILE" ]; then
    echo -e "${RED}Error: Use only one of --notes or --notes-file${NC}"
    exit 1
fi

# If using notes-file, verify file exists
if [ -n "$NOTES_FILE" ] && [ ! -f "$NOTES_FILE" ]; then
    echo -e "${RED}Error: Notes file not found: ${NOTES_FILE}${NC}"
    exit 1
fi

USE_PR_NOTES=true
if [ -n "$NOTES_STRING" ] || [ -n "$NOTES_FILE" ]; then
    USE_PR_NOTES=false
fi

TAG_NAME="py/v${VERSION}"

echo -e "${BLUE}=== Genkit Python SDK Release: v${VERSION} ===${NC}"
echo ""

# Check we're in the py directory or repo root
if [ -f "pyproject.toml" ] && [ -d "packages" ]; then
    # We're in py/
    cd ..
elif [ -d "py/packages" ]; then
    # We're in repo root
    :
else
    echo -e "${RED}Error: Must run from repo root or py/ directory${NC}"
    exit 1
fi

# Navigate to py/ for version checks
cd py

# Step 1: Verify version in packages
echo -e "${YELLOW}Step 1: Verifying package versions...${NC}"
GENKIT_VERSION=$(grep "^version = " packages/genkit/pyproject.toml | cut -d'"' -f2)
if [ "$GENKIT_VERSION" != "$VERSION" ]; then
    echo -e "${RED}Error: genkit package version is ${GENKIT_VERSION}, expected ${VERSION}${NC}"
    echo "Update packages/genkit/pyproject.toml before creating release"
    exit 1
fi
echo -e "${GREEN}✓ Package version matches: ${VERSION}${NC}"

# Go back to repo root
cd ..

# Step 2: Verify git status
echo ""
echo -e "${YELLOW}Step 2: Checking git status...${NC}"
CURRENT_BRANCH=$(git branch --show-current)
if [ "$CURRENT_BRANCH" != "main" ] && [ "${SKIP_BRANCH_CHECK:-}" != "1" ]; then
    echo -e "${RED}Error: Not on main branch (currently on: ${CURRENT_BRANCH})${NC}"
    echo "Switch to main branch: git checkout main"
    echo "Or set SKIP_BRANCH_CHECK=1 to override (testing only)"
    exit 1
fi
echo -e "${GREEN}✓ On branch: ${CURRENT_BRANCH}${NC}"

# Check for uncommitted changes
if ! git diff-index --quiet HEAD --; then
    echo -e "${RED}Error: There are uncommitted changes${NC}"
    echo "Commit or stash changes before creating release"
    exit 1
fi
echo -e "${GREEN}✓ No uncommitted changes${NC}"

# Step 3: Pull latest
echo ""
echo -e "${YELLOW}Step 3: Pulling latest changes...${NC}"
git pull origin main
echo -e "${GREEN}✓ Pulled latest from origin/main${NC}"

# Step 4 & 5: Get release notes (from PR or --notes/--notes-file)
RELEASE_NOTES_FILE=$(mktemp)
trap 'rm -f "$RELEASE_NOTES_FILE"' EXIT

if [ "$USE_PR_NOTES" = true ]; then
    echo ""
    echo -e "${YELLOW}Step 4: Finding release PR...${NC}"
    if [ -z "$PR_NUMBER" ]; then
        # Auto-find the merged PR for this version
        PR_NUMBER=$(gh pr list --repo firebase/genkit --state merged \
            --search "Python SDK ${VERSION} in:title" \
            --json number --limit 1 | jq -r '.[0].number // empty')
        
        if [ -z "$PR_NUMBER" ]; then
            # Try searching by version in body
            PR_NUMBER=$(gh pr list --repo firebase/genkit --state merged \
                --search "v${VERSION} label:python" \
                --json number --limit 1 | jq -r '.[0].number // empty')
        fi
        
        if [ -z "$PR_NUMBER" ]; then
            echo -e "${RED}Error: Could not find merged PR for version ${VERSION}${NC}"
            echo "Specify PR number manually: $0 ${VERSION} <PR_NUMBER>"
            echo "Or use --notes or --notes-file for release candidates"
            exit 1
        fi
    fi

    echo -e "${GREEN}✓ Found PR #${PR_NUMBER}${NC}"

    echo ""
    echo -e "${YELLOW}Step 5: Fetching PR description...${NC}"
    gh pr view "$PR_NUMBER" --repo firebase/genkit --json body --jq '.body' > "$RELEASE_NOTES_FILE"

    if [ ! -s "$RELEASE_NOTES_FILE" ]; then
        echo -e "${RED}Error: PR #${PR_NUMBER} has no description${NC}"
        exit 1
    fi

    LINE_COUNT=$(wc -l < "$RELEASE_NOTES_FILE")
    echo -e "${GREEN}✓ Fetched PR description (${LINE_COUNT} lines)${NC}"
else
    echo ""
    echo -e "${YELLOW}Step 4: Using provided release notes...${NC}"
    if [ -n "$NOTES_FILE" ]; then
        cp "$NOTES_FILE" "$RELEASE_NOTES_FILE"
        echo -e "${GREEN}✓ Using notes from ${NOTES_FILE}${NC}"
    else
        echo "$NOTES_STRING" > "$RELEASE_NOTES_FILE"
        echo -e "${GREEN}✓ Using inline notes${NC}"
    fi
fi

# Step 6: Check if tag already exists
echo ""
echo -e "${YELLOW}Step 6: Checking if tag exists...${NC}"
if git tag -l "$TAG_NAME" | grep -q "$TAG_NAME"; then
    echo -e "${RED}Error: Tag ${TAG_NAME} already exists${NC}"
    echo "Delete it first if you need to recreate: git tag -d ${TAG_NAME} && git push origin :refs/tags/${TAG_NAME}"
    exit 1
fi
echo -e "${GREEN}✓ Tag ${TAG_NAME} does not exist${NC}"

# Step 7: Create tag
echo ""
echo -e "${YELLOW}Step 7: Creating annotated tag...${NC}"
if [ "$USE_PR_NOTES" = true ]; then
    TAG_MSG="Genkit Python SDK v${VERSION}

Release highlights:
- See py/CHANGELOG.md for full release notes
- Based on PR #${PR_NUMBER}

Published packages:
- genkit (core)
- genkit-plugin-* (22 plugins)"
else
    TAG_MSG="Genkit Python SDK v${VERSION}

Release highlights:
- See py/CHANGELOG.md for full release notes

Published packages:
- genkit (core)
- genkit-plugin-* (22 plugins)"
fi
git tag -a "$TAG_NAME" -m "$TAG_MSG"

echo -e "${GREEN}✓ Created tag: ${TAG_NAME}${NC}"

# Step 8: Push tag
echo ""
echo -e "${YELLOW}Step 8: Pushing tag to origin...${NC}"
git push origin "$TAG_NAME"
echo -e "${GREEN}✓ Pushed tag to origin${NC}"

# Step 9: Create GitHub release
echo ""
echo -e "${YELLOW}Step 9: Creating GitHub release...${NC}"
GH_RELEASE_ARGS=(--title "Genkit Python SDK v${VERSION}" --notes-file "$RELEASE_NOTES_FILE")
if [[ "$VERSION" =~ rc[0-9]*$ ]] || [[ "$VERSION" =~ -rc\.[0-9]+$ ]]; then
    GH_RELEASE_ARGS+=(--prerelease)
fi
gh release create "$TAG_NAME" "${GH_RELEASE_ARGS[@]}"

echo -e "${GREEN}✓ Created GitHub release${NC}"

# Summary
echo ""
echo -e "${BLUE}=== Release Created Successfully ===${NC}"
echo ""
echo "Tag: ${TAG_NAME}"
if [ "$USE_PR_NOTES" = true ]; then
    echo "Based on PR: #${PR_NUMBER}"
fi
echo "Release: https://github.com/genkit-ai/genkit/releases/tag/${TAG_NAME}"
echo ""
echo -e "${YELLOW}Next steps:${NC}"
echo "1. Go to Actions → Publish Python Package"
echo "2. Run workflow with: publish_scope=all"
echo "3. Monitor the publish workflow"
echo "4. Verify on PyPI: pip index versions genkit"
