#!/usr/bin/env bash
# Full release pipeline for a BW plugin.
# Usage: tools/release.sh bw-<slug> [version]

source "$(dirname "$0")/lib/common.sh"

SLUG="${1:-}"
VERSION_ARG="${2:-}"

require_rian
require_slug "$SLUG"

PLUGIN_DIR="${BW_PLUGINS_DIR}/${SLUG}"
HDR_VER=$(plugin_header_version "$SLUG")
VERSION="${VERSION_ARG:-$HDR_VER}"

[[ "$VERSION" == "$HDR_VER" ]] || die "Argument version ${VERSION} does not match plugin header ${HDR_VER}. Run bump-version.sh first."

log_info "${BOLD}Releasing ${SLUG} v${VERSION}${RESET}"

# 1. Changelog must have a real entry for this version.
if ! grep -qE "^## \[${VERSION}\]" "${PLUGIN_DIR}/CHANGELOG.md"; then
	die "CHANGELOG.md has no entry for ${VERSION}"
fi

# 2. Source snapshot BEFORE touching anything.
SNAP_DIR="${BW_RELEASES_DIR}/${SLUG}/${VERSION}"
mkdir -p "$SNAP_DIR"
tar czf "${SNAP_DIR}/source-snapshot.tar.gz" -C "${BW_PLUGINS_DIR}" "${SLUG}"
log_ok "Source snapshot: ${SNAP_DIR}/source-snapshot.tar.gz"

# 3. Test.
log_info "Running test-plugin..."
"${BW_REPO_ROOT}/tools/test-plugin.sh" "$SLUG" || die "test-plugin failed"

# 4. Security scan.
log_info "Running security-scan..."
"${BW_REPO_ROOT}/tools/security-scan.sh" "$SLUG" || die "security-scan failed"

# 5. Cleanup scan.
log_info "Running cleanup-scan..."
"${BW_REPO_ROOT}/tools/cleanup-scan.sh" "$SLUG" || die "cleanup-scan failed"

# 6. Build zip.
log_info "Building zip..."
BUILD_DIR=$(mktemp -d -t "bw-release-${SLUG}-XXXXXX")
trap 'rm -rf "$BUILD_DIR"' EXIT
STAGE="${BUILD_DIR}/${SLUG}"
mkdir -p "$STAGE"

rsync -a \
	--exclude='docs/' \
	--exclude='tests/' \
	--exclude='.git/' \
	--exclude='.github/' \
	--exclude='CLAUDE.md' \
	--exclude='HANDOFF-NOTES.md' \
	--exclude='SESSION-LOG.md' \
	--exclude='debug-*.php' \
	--exclude='test-*.php' \
	--exclude='scratch-*.php' \
	--exclude='scratch/' \
	--exclude='.DS_Store' \
	--exclude='*.swp' \
	--exclude='*.swo' \
	--exclude='*~' \
	--exclude='Thumbs.db' \
	--exclude='node_modules/' \
	--exclude='.security-allowlist' \
	--exclude='.cleanup-allowlist' \
	--exclude='phpcs.xml' \
	--exclude='phpunit.xml' \
	--exclude='composer.lock' \
	--exclude='package-lock.json' \
	--exclude='.editorconfig' \
	--exclude='.eslintrc*' \
	--exclude='.prettierrc*' \
	"${PLUGIN_DIR}/" "${STAGE}/"

ZIP="${BUILD_DIR}/${SLUG}-${VERSION}.zip"
(cd "$BUILD_DIR" && zip -rq "$ZIP" "$SLUG")
SHA=$(sha256_of "$ZIP")
SIZE=$(stat -c%s "$ZIP")
log_ok "Built ${SLUG}-${VERSION}.zip (${SIZE} bytes, sha256:${SHA:0:16}...)"

# 7. Extract changelog section for this version.
CHANGELOG_SECTION=$(awk -v ver="$VERSION" '
	$0 ~ "^## \\[" ver "\\]" { capture=1; print; next }
	capture && /^## \[/ { exit }
	capture { print }
' "${PLUGIN_DIR}/CHANGELOG.md")

# 8. Build sidecar metadata.
NAME=$(plugin_header_field "$SLUG" "Plugin Name")
DESC=$(plugin_header_field "$SLUG" "Description")
REQ_WP=$(plugin_header_field "$SLUG" "Requires at least")
TESTED_WP=$(plugin_header_field "$SLUG" "Tested up to" || echo "")
REQ_PHP=$(plugin_header_field "$SLUG" "Requires PHP")
HOMEPAGE="https://plugins.bowden.works/${SLUG}/"
AUTHOR="Bowden Works"

META_JSON=$(cat <<EOF
{
  "slug": "${SLUG}",
  "name": "${NAME}",
  "version": "${VERSION}",
  "download_url": "${BW_DIST_DOWNLOAD_BASE}/${SLUG}-${VERSION}.zip",
  "download_hash": "sha256:${SHA}",
  "download_size": ${SIZE},
  "requires": "${REQ_WP}",
  "tested": "${TESTED_WP}",
  "requires_php": "${REQ_PHP}",
  "last_updated": "$(date -u +%Y-%m-%d)",
  "homepage": "${HOMEPAGE}",
  "author": "${AUTHOR}",
  "description": $(printf '%s' "$DESC" | jq -Rs .),
  "changelog": $(printf '%s' "$CHANGELOG_SECTION" | jq -Rs .)
}
EOF
)

# 9. Publish to dist host (if present).
if [[ ! -d "$BW_DIST_UPDATES_DIR" ]]; then
	log_warn "Dist updates dir not found: ${BW_DIST_UPDATES_DIR}"
	log_warn "Skipping publish step. Zip + meta saved to snapshot dir only."
	cp "$ZIP" "${SNAP_DIR}/${SLUG}-${VERSION}.zip"
	printf '%s\n' "$META_JSON" > "${SNAP_DIR}/${SLUG}-${VERSION}.meta.json"
else
	log_info "Publishing to ${BW_DIST_UPDATES_DIR}..."
	# Write via sg to get the bw-plugins-dist-dev group (session may not have it active).
	META_TMP="${BUILD_DIR}/${SLUG}-${VERSION}.meta.json"
	printf '%s\n' "$META_JSON" > "$META_TMP"
	if sg bw-plugins-dist-dev -c "cp '$ZIP' '${BW_DIST_UPDATES_DIR}/${SLUG}-${VERSION}.zip' && cp '$META_TMP' '${BW_DIST_UPDATES_DIR}/${SLUG}-${VERSION}.meta.json' && chmod 644 '${BW_DIST_UPDATES_DIR}/${SLUG}-${VERSION}.zip' '${BW_DIST_UPDATES_DIR}/${SLUG}-${VERSION}.meta.json'"; then
		log_ok "Published"
	else
		log_error "Failed to publish to ${BW_DIST_UPDATES_DIR}"
		exit 1
	fi
fi

# Always keep a copy in the release snapshot dir.
cp "$ZIP" "${SNAP_DIR}/${SLUG}-${VERSION}.zip"
printf '%s\n' "$META_JSON" > "${SNAP_DIR}/${SLUG}-${VERSION}.meta.json"

# 10. Record in release history.
HISTORY_ENTRY=$(jq -n \
	--arg slug "$SLUG" \
	--arg version "$VERSION" \
	--arg sha "$SHA" \
	--arg when "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
	--arg who "$(id -un)" \
	'{slug: $slug, version: $version, sha256: $sha, released_at: $when, released_by: $who}')

if [[ -f "$BW_RELEASE_HISTORY" ]]; then
	jq ". + [${HISTORY_ENTRY}]" "$BW_RELEASE_HISTORY" > "${BW_RELEASE_HISTORY}.tmp" \
		&& mv "${BW_RELEASE_HISTORY}.tmp" "$BW_RELEASE_HISTORY"
else
	echo "[${HISTORY_ENTRY}]" > "$BW_RELEASE_HISTORY"
fi

# 11. Post-release verification.
if [[ -d "$BW_DIST_UPDATES_DIR" ]]; then
	log_info "Verifying dist host..."
	sleep 2
	REMOTE_URL="${BW_DIST_UPDATE_URL}?slug=${SLUG}"
	if remote_ver=$(curl -sf --max-time 10 "$REMOTE_URL" | jq -r '.version' 2>/dev/null); then
		if [[ "$remote_ver" == "$VERSION" ]]; then
			log_ok "Dist host serves ${VERSION}"
		else
			log_warn "Dist host serves '${remote_ver}' but expected '${VERSION}' (cache?)"
		fi
	else
		log_warn "Could not reach REST endpoint at ${REMOTE_URL} (dist host may not be set up yet)"
	fi
fi

echo
log_ok "${BOLD}Released ${SLUG} v${VERSION}${RESET}"
echo "  Manifest: ${BW_DIST_UPDATE_URL}?slug=${SLUG}"
echo "  Download: ${BW_DIST_DOWNLOAD_BASE}/${SLUG}-${VERSION}.zip"
echo "  SHA-256:  ${SHA}"
echo "  Snapshot: ${SNAP_DIR}"
