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

# ── Configuration ──────────────────────────────────────────────
GITEA_URL="https://code.crashlabs.io"
REPO="dave/storkit"
BINARY_NAME="storkit"

# ── Load .env if present ───────────────────────────────────────
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
if [ -f "${SCRIPT_DIR}/.env" ]; then
  set -a
  source "${SCRIPT_DIR}/.env"
  set +a
fi

# ── Preflight ──────────────────────────────────────────────────
if [ -z "${GITEA_TOKEN:-}" ]; then
  echo "Error: GITEA_TOKEN is not set."
  echo "Create a token at ${GITEA_URL}/user/settings/applications"
  echo "Then add to .env:  GITEA_TOKEN=your_token"
  exit 1
fi

VERSION="${1:-}"
if [ -z "$VERSION" ]; then
  echo "Usage: script/release <version>"
  echo "Example: script/release 0.2.0"
  exit 1
fi

TAG="v${VERSION}"

if git rev-parse "$TAG" >/dev/null 2>&1; then
  echo "Error: Tag ${TAG} already exists."
  exit 1
fi

# ── Bump version in Cargo.toml ────────────────────────────────
CARGO_TOML="${SCRIPT_DIR}/server/Cargo.toml"
if ! grep -q "^version = " "$CARGO_TOML"; then
  echo "Error: Could not find version field in ${CARGO_TOML}"
  exit 1
fi
sed -i '' "s/^version = \".*\"/version = \"${VERSION}\"/" "$CARGO_TOML"
echo "==> Bumped ${CARGO_TOML} to ${VERSION}"

PACKAGE_JSON="${SCRIPT_DIR}/frontend/package.json"
sed -i '' "s/\"version\": \".*\"/\"version\": \"${VERSION}\"/" "$PACKAGE_JSON"
echo "==> Bumped ${PACKAGE_JSON} to ${VERSION}"

# Regenerate lock files so they stay in sync with the version bump.
CARGO_LOCK="${SCRIPT_DIR}/Cargo.lock"
(cd "${SCRIPT_DIR}/server" && cargo generate-lockfile)
echo "==> Regenerated Cargo.lock"

PACKAGE_LOCK="${SCRIPT_DIR}/frontend/package-lock.json"
(cd "${SCRIPT_DIR}/frontend" && npm install --package-lock-only --ignore-scripts --silent 2>/dev/null)
echo "==> Regenerated package-lock.json"

git add "$CARGO_TOML" "$CARGO_LOCK" "$PACKAGE_JSON" "$PACKAGE_LOCK"
git commit -m "Bump version to ${VERSION}"

if ! command -v cross >/dev/null 2>&1; then
  echo "Error: 'cross' is not installed. Run: cargo install cross"
  exit 1
fi

if ! docker info >/dev/null 2>&1; then
  echo "Error: Docker is not running. Start Docker Desktop first."
  exit 1
fi

echo "==> Releasing ${TAG}"

# ── Build ──────────────────────────────────────────────────────
echo "==> Building macOS (native)..."
cargo build --release

echo "==> Building Linux (static musl via cross)..."
cross build --release --target x86_64-unknown-linux-musl

# ── Package ────────────────────────────────────────────────────
DIST="target/dist"
rm -rf "$DIST"
mkdir -p "$DIST"

cp "target/release/${BINARY_NAME}" "${DIST}/${BINARY_NAME}-macos-arm64"
cp "target/x86_64-unknown-linux-musl/release/${BINARY_NAME}" "${DIST}/${BINARY_NAME}-linux-amd64"
chmod +x "${DIST}"/*

echo "==> Binaries:"
ls -lh "${DIST}"/

# ── Changelog ──────────────────────────────────────────────────
echo "==> Generating changelog..."
PREV_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
if [ -n "$PREV_TAG" ]; then
  LOG_RANGE="${PREV_TAG}..HEAD"
  RANGE="${PREV_TAG}...${TAG}"
else
  LOG_RANGE=""
  RANGE="initial...${TAG}"
fi

# Extract completed stories/bugs/refactors from merge commits.
# Matches both the current "storkit:" prefix and the legacy "story-kit:" prefix.
# Deduplicate (a story may have been merged more than once after reverts).
MERGE_RE="^(storkit|story-kit): merge "
if [ -n "$LOG_RANGE" ]; then
  MERGED_RAW=$(git log "$LOG_RANGE" --pretty=format:"%s" --no-merges \
    | grep -E "$MERGE_RE" | sed -E "s/$MERGE_RE//" | sort -u)
else
  MERGED_RAW=$(git log --pretty=format:"%s" --no-merges \
    | grep -E "$MERGE_RE" | sed -E "s/$MERGE_RE//" | sort -u)
fi

# Categorise merged work items and format names.
FEATURES=""
FIXES=""
REFACTORS=""
while IFS= read -r item; do
  [ -z "$item" ] && continue
  # Strip the numeric prefix and type to get the human name.
  name=$(echo "$item" | sed -E 's/^[0-9]+_(story|bug|refactor|spike)_//' | tr '_' ' ')
  # Capitalise first letter.
  name="$(echo "${name:0:1}" | tr '[:lower:]' '[:upper:]')${name:1}"
  case "$item" in
    *_bug_*)     FIXES="${FIXES}- ${name}\n" ;;
    *_refactor_*) REFACTORS="${REFACTORS}- ${name}\n" ;;
    *)           FEATURES="${FEATURES}- ${name}\n" ;;
  esac
done <<< "$MERGED_RAW"

# Collect non-automation manual commits (direct fixes, version bumps, etc).
if [ -n "$LOG_RANGE" ]; then
  MANUAL=$(git log "$LOG_RANGE" --pretty=format:"%s" --no-merges \
    | grep -Ev "^(storkit|story-kit): " \
    | grep -Ev "^Revert \"(storkit|story-kit): " \
    | grep -v "^Bump version" \
    | sed 's/^/- /')
else
  MANUAL=$(git log --pretty=format:"%s" --no-merges \
    | grep -Ev "^(storkit|story-kit): " \
    | grep -Ev "^Revert \"(storkit|story-kit): " \
    | grep -v "^Bump version" \
    | sed 's/^/- /')
fi

# ── Generate summary overview ─────────────────────────────────
# Group completed items by keyword clusters to identify the
# release's focus areas.
generate_summary() {
  local all_items="$1"
  local themes=""

  # Count items matching each theme keyword (one item per line via echo -e)
  local expanded
  expanded=$(echo -e "$all_items")
  local bot_count=$(echo "$expanded" | grep -icE 'bot|command|chat|matrix|slack|whatsapp|status|help|assign|rebuild|shutdown|whatsup' || true)
  local mcp_count=$(echo "$expanded" | grep -icE 'mcp|tool' || true)
  local docker_count=$(echo "$expanded" | grep -icE 'docker|container|gvisor|orbstack|harden|security' || true)
  local agent_count=$(echo "$expanded" | grep -icE 'agent|runtime|chatgpt|gemini|openai|model|coder' || true)
  local ui_count=$(echo "$expanded" | grep -icE 'frontend|ui|web|oauth|scaffold' || true)
  local infra_count=$(echo "$expanded" | grep -icE 'release|makefile|refactor|upgrade|worktree|pipeline' || true)

  # Build theme list, highest count first
  local -a theme_pairs=()
  [ "$agent_count" -gt 0 ] && theme_pairs+=("${agent_count}:multi-model agents")
  [ "$bot_count" -gt 0 ] && theme_pairs+=("${bot_count}:bot commands")
  [ "$mcp_count" -gt 0 ] && theme_pairs+=("${mcp_count}:MCP tools")
  [ "$docker_count" -gt 0 ] && theme_pairs+=("${docker_count}:Docker hardening")
  [ "$ui_count" -gt 0 ] && theme_pairs+=("${ui_count}:developer experience")
  [ "$infra_count" -gt 0 ] && theme_pairs+=("${infra_count}:infrastructure")

  # Sort by count descending, take top 3
  local sorted=$(printf '%s\n' "${theme_pairs[@]}" | sort -t: -k1 -nr | head -3)
  local labels=""
  while IFS=: read -r count label; do
    [ -z "$label" ] && continue
    if [ -z "$labels" ]; then
      # Capitalise first theme
      labels="$(echo "${label:0:1}" | tr '[:lower:]' '[:upper:]')${label:1}"
    else
      labels="${labels}, ${label}"
    fi
  done <<< "$sorted"

  echo "$labels"
}

ALL_ITEMS="${FEATURES}${FIXES}${REFACTORS}"
SUMMARY=$(generate_summary "$ALL_ITEMS")
if [ -n "$SUMMARY" ]; then
  SUMMARY_LINE="**Focus:** ${SUMMARY}"
else
  SUMMARY_LINE=""
fi

# Assemble the release body.
RELEASE_BODY="## What's Changed"

if [ -n "$SUMMARY_LINE" ]; then
  RELEASE_BODY="${RELEASE_BODY}

${SUMMARY_LINE}"
fi

if [ -n "$FEATURES" ]; then
  RELEASE_BODY="${RELEASE_BODY}

### Features
$(echo -e "$FEATURES")"
fi

if [ -n "$FIXES" ]; then
  RELEASE_BODY="${RELEASE_BODY}

### Bug Fixes
$(echo -e "$FIXES")"
fi

if [ -n "$REFACTORS" ]; then
  RELEASE_BODY="${RELEASE_BODY}

### Refactors
$(echo -e "$REFACTORS")"
fi

if [ -n "$MANUAL" ]; then
  RELEASE_BODY="${RELEASE_BODY}

### Other Changes
${MANUAL}"
fi

if [ -z "$FEATURES" ] && [ -z "$FIXES" ] && [ -z "$REFACTORS" ] && [ -z "$MANUAL" ]; then
  RELEASE_BODY="${RELEASE_BODY}

- No changes since last release"
fi

RELEASE_BODY="${RELEASE_BODY}

**Full diff:** ${GITEA_URL}/${REPO}/compare/${RANGE}"

echo "$RELEASE_BODY"

# ── Tag & Push ─────────────────────────────────────────────────
echo "==> Tagging ${TAG}..."
git tag -a "$TAG" -m "Release ${TAG}"
git push origin "$TAG"

# ── Create Gitea Release ──────────────────────────────────────
echo "==> Creating release on Gitea..."
RELEASE_JSON_FILE=$(mktemp)
trap "rm -f '$RELEASE_JSON_FILE'" EXIT
python3 -c "
import json, sys
with open(sys.argv[3], 'w') as f:
    json.dump({
        'tag_name': sys.argv[1],
        'name': sys.argv[1],
        'body': sys.argv[2]
    }, f)
" "$TAG" "$RELEASE_BODY" "$RELEASE_JSON_FILE"

RELEASE_RESPONSE=$(curl -s --fail-with-body -X POST \
  -H "Authorization: token ${GITEA_TOKEN}" \
  -H "Content-Type: application/json" \
  "${GITEA_URL}/api/v1/repos/${REPO}/releases" \
  -d "@${RELEASE_JSON_FILE}")

if [ $? -ne 0 ]; then
  echo "Error: Failed to create Gitea release."
  echo "Response: ${RELEASE_RESPONSE}"
  exit 1
fi

RELEASE_ID=$(echo "$RELEASE_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")

# ── Upload Binaries ───────────────────────────────────────────
for file in "${DIST}"/*; do
  filename=$(basename "$file")
  echo "==> Uploading ${filename}..."
  curl -sf -X POST \
    -H "Authorization: token ${GITEA_TOKEN}" \
    -F "attachment=@${file};filename=${filename}" \
    "${GITEA_URL}/api/v1/repos/${REPO}/releases/${RELEASE_ID}/assets" > /dev/null
done

echo ""
echo "==> Done! Release ${TAG} published:"
echo "    ${GITEA_URL}/${REPO}/releases/tag/${TAG}"
