#!/usr/bin/env bash
# TrainUs release script — local steps only.
# Prepares a release commit, tag, source archive, and a draft release notes file.
# Everything that touches Forgejo or a remote server is left to you (see checklist at the end).
# Usage: ./scripts/release.sh
set -euo pipefail

GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; BOLD='\033[1m'; NC='\033[0m'
RED='\033[0;31m'; DIM='\033[2m'
info()  { echo -e "  ${GREEN}✓${NC} $*"; }
doing() { echo -e "\n${CYAN}▶${NC} $*"; }
warn()  { echo -e "  ${YELLOW}⚠${NC} $*"; }
error() { echo -e "\n${RED}✗ Error:${NC} $*" >&2; exit 1; }

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
cd "$ROOT_DIR"

# Print a recovery hint if the script dies between the version bump and the commit.
BUMPED=0
COMMITTED=0
on_exit() {
  if [[ $? -ne 0 && "$BUMPED" == "1" && "$COMMITTED" == "0" ]]; then
    echo -e "\n${YELLOW}⚠ Release interrupted after the version bump.${NC}" >&2
    echo "  To undo it: git checkout -- package.json package-lock.json" >&2
  fi
}
trap on_exit EXIT

# ── Prerequisites ─────────────────────────────────────────────────────────────
echo ""
echo -e "${BOLD}Checking prerequisites...${NC}"

command -v npm >/dev/null 2>&1 || error "npm is not installed."
command -v git >/dev/null 2>&1 || error "git is not installed."
info "npm and git are available."

if [[ -n "$(git status --porcelain)" ]]; then
  error "Working tree is not clean. Commit or stash your changes before releasing."
fi
info "Working tree is clean."

CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
if [[ "$CURRENT_BRANCH" != "main" ]]; then
  warn "Current branch is '$CURRENT_BRANCH', not 'main'."
fi
info "On branch: $CURRENT_BRANCH"

# ── Quality gate ──────────────────────────────────────────────────────────────
echo ""
echo -e "${BOLD}Quality gate${NC}"

echo "  Running: npm run lint"
npm run lint --silent || error "Lint failed. Fix the issues before releasing."
info "Lint passed."

echo "  Running: npm run format:check"
npm run format:check --silent || error "Formatting check failed. Run 'npm run format' and commit."
info "Formatting is clean."

echo -n "  Run the Playwright test suite now? (slow) [Y/n] "
read -r RUN_TESTS
if [[ "$RUN_TESTS" =~ ^[Nn] ]]; then
  warn "Tests skipped — make sure the suite passed recently."
else
  echo "  Running: npm run test:parallel"
  npm run test:parallel || error "Tests failed. Fix them before releasing."
  info "Tests passed on Firefox and Chromium."
fi

# ── Commits since last release ────────────────────────────────────────────────
echo ""
echo -e "${BOLD}Changes since last release${NC}"

LAST_TAG=$(git describe --tags --abbrev=0 HEAD 2>/dev/null || echo "")

if [[ -n "$LAST_TAG" ]]; then
  echo "  Last release: $LAST_TAG"
  echo "  Commits since $LAST_TAG:"
  echo ""
  COMMIT_LOG=$(git log "${LAST_TAG}..HEAD" --oneline --no-merges)
  if [[ -z "$COMMIT_LOG" ]]; then
    warn "No commits since $LAST_TAG. Are you sure you want to release?"
  else
    while IFS= read -r line; do
      echo -e "  ${DIM}${line}${NC}"
    done <<< "$COMMIT_LOG"
  fi
else
  COMMIT_LOG=""
  info "No previous tag — this is the first release."
fi

echo ""

# ── Version ───────────────────────────────────────────────────────────────────
echo -e "${BOLD}Version${NC}"
CURRENT_VERSION=$(node -p "require('./package.json').version")
echo "  Current version: $CURRENT_VERSION"
echo -n "  New version (semver, e.g. 1.1.0): "
read -r VERSION

[[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] \
  || error "Invalid format. Use MAJOR.MINOR.PATCH without a 'v' prefix."

TAG="v$VERSION"
mkdir -p tmp
ARCHIVE="tmp/trainus-${TAG}-src.zip"
NOTES_FILE="tmp/trainus-${TAG}-notes.md"

git tag --list | grep -q "^${TAG}$" \
  && error "Tag $TAG already exists locally."

# ── Plan ──────────────────────────────────────────────────────────────────────
echo ""
echo -e "${BOLD}The script will perform the following steps in order:${NC}"
echo ""
echo "  1. Bump version in package.json and package-lock.json"
echo "       $CURRENT_VERSION  →  $VERSION"
echo ""
echo "  2. Build the production app"
echo "       npm run build  →  dist/"
echo ""
echo "  3. Create a release commit on branch '$CURRENT_BRANCH'"
echo "       git commit -m \"chore: release $TAG\""
echo ""
echo "  4. Create an annotated git tag (local only, not pushed)"
echo "       git tag -a $TAG -m \"Release $TAG\""
echo ""
echo "  5. Create a source archive of the current commit"
echo "       $ARCHIVE  (tracked files only, no node_modules, no dist)"
echo ""
echo "  6. Generate a draft release notes file for you to edit"
echo "       $NOTES_FILE  (pre-filled draft to edit)"
echo ""
echo -e "${YELLOW}Nothing will be pushed or sent anywhere. All steps are local.${NC}"
echo ""
echo -n "  Continue? [y/N] "
read -r CONFIRM
[[ "$CONFIRM" =~ ^[Yy]$ ]] || { echo "  Aborted."; exit 0; }

# ── Step 1 — Bump version ─────────────────────────────────────────────────────
doing "Step 1/6 — Bumping version in package.json and package-lock.json"
echo "  Running: npm version $VERSION --no-git-tag-version"
npm version "$VERSION" --no-git-tag-version --silent
BUMPED=1
info "package.json and package-lock.json updated to $VERSION."

# ── Step 2 — Build ────────────────────────────────────────────────────────────
doing "Step 2/6 — Building the production app"
echo "  Running: npm run build"
npm run build
info "Build complete. Output is in dist/."

# ── Step 3 — Commit ───────────────────────────────────────────────────────────
doing "Step 3/6 — Creating release commit"
echo "  Running: git add package.json package-lock.json"
echo "           git commit -m \"chore: release $TAG\""
git add package.json package-lock.json
git commit -m "chore: release $TAG"
COMMITTED=1
info "Commit created: chore: release $TAG"

# ── Step 4 — Tag ──────────────────────────────────────────────────────────────
doing "Step 4/6 — Creating annotated git tag"
echo "  Running: git tag -a $TAG -m \"Release $TAG\""
git tag -a "$TAG" -m "Release $TAG"
info "Tag $TAG created locally."

# ── Step 5 — Archive ──────────────────────────────────────────────────────────
doing "Step 5/6 — Creating source archive"
echo "  Running: git archive --format=zip HEAD --output=$ARCHIVE"
git archive --format=zip HEAD --output="$ARCHIVE"
info "Archive created: $ARCHIVE"
echo "  Contains: all files tracked by git at commit $(git rev-parse --short HEAD)."
echo "  Excludes: node_modules/, dist/, .git/, and any untracked files."

# ── Step 6 — Release notes file ───────────────────────────────────────────────
doing "Step 6/6 — Generating draft release notes"
echo "  Writing: $NOTES_FILE"

{
  echo "# TrainUs $TAG — Release notes"
  echo ""
  if [[ -z "$LAST_TAG" ]]; then
    echo "First release $VERSION."
  else
    echo "<!-- Edit this file before pasting into Forgejo. Delete comments. -->"
    echo ""
    echo "## What's new"
    echo ""
    echo "<!-- Describe new features. -->"
    echo ""
    echo "-"
    echo ""
    echo "## Bug fixes"
    echo ""
    echo "<!-- List bug fixes, or remove this section if none. -->"
    echo ""
    echo "-"
    echo ""
    echo "## Breaking changes"
    echo ""
    echo "None."
    echo ""
    echo "---"
    echo ""
    echo "## Commits since $LAST_TAG"
    echo ""
    echo "<!-- For reference — trim or reword before publishing. -->"
    echo ""
    if [[ -n "$COMMIT_LOG" ]]; then
      while IFS= read -r line; do
        echo "- $line"
      done <<< "$COMMIT_LOG"
    else
      echo "- (none)"
    fi
  fi
} > "$NOTES_FILE"

info "Draft release notes written to $NOTES_FILE."
echo "  Open it in your editor, rewrite the notes, then paste into Forgejo."

# ── Done — Manual checklist ───────────────────────────────────────────────────
echo ""
echo -e "${GREEN}${BOLD}Local release steps complete.${NC}"
echo ""
echo -e "${BOLD}Artifacts created:${NC}"
echo "  $ARCHIVE       ← attach to the Forgejo release"
echo "  $NOTES_FILE    ← edit and paste as the release body"
echo ""
echo -e "${BOLD}Manual steps remaining:${NC}"
echo ""
echo -e "  ${BOLD}1. Edit the release notes${NC}"
echo "       Open $NOTES_FILE and rewrite the notes into polished prose."
echo ""
echo -e "  ${BOLD}2. Push the commit and tag to Forgejo${NC}"
echo "       git push origin $CURRENT_BRANCH"
echo "       git push origin $TAG"
echo ""
echo -e "  ${BOLD}3. Create the release on Forgejo${NC}"
echo "       Go to your repository → Releases → New release"
echo "       Tag:    $TAG"
echo "       Title:  TrainUs $TAG"
echo "       Body:   paste the contents of $NOTES_FILE"
echo "       Attach: $ARCHIVE"
echo "       Publish the release."
echo ""
echo -e "  ${BOLD}4. Deploy the app${NC}"
echo "       Upload the contents of dist/ to your static host."
echo ""
echo -e "  ${BOLD}5. Deploy the website${NC}"
echo "       npm run site:build"
echo "       Upload the contents of website/public/ to your website host."
echo ""
echo -e "  ${BOLD}6. Publish the release blog post${NC}"
echo "       Duplicate website/content/blog/release-template.en.md"
echo "       Rename it: $(date +%Y-%m-%d)-release-${TAG}.en.md"
echo "       Fill in the placeholders — set draft: false when ready."
echo "       Write the French version yourself."
echo "       Rebuild and redeploy the website (step 5)."
echo ""
echo -e "  ${BOLD}7. Clean up local artifacts (optional — tmp/ is gitignored)${NC}"
echo "       Once uploaded and published: rm $ARCHIVE $NOTES_FILE"
echo ""
