#!/bin/bash
# release.sh - Build a release artifact and create a Gitea release via `tea`
#
# Usage:
#   scripts/release.sh [VERSION]
#
# If VERSION is not given, it is read from the latest git tag (e.g. v0.1.5).
# Falls back to "dev" if no tag is found.
#
# Steps:
#   1. Validate toolchain (git, go, tar, tea)
#   2. Determine version
#   3. Build orca binary with version injection via -ldflags
#   4. Package as tarball: orca-${VERSION}-${OS}-${ARCH}.tar.gz
#   5. Generate release notes from `---ci---` blocks since last tag
#   6. Invoke `tea releases create` to publish to Gitea
#
# Requires:
#   - GITEA_TOKEN environment variable
#   - `tea` CLI on PATH (https://gitea.com/gitea/tea)
#
# Idempotent: tea releases create will fail if the release already exists;
# the script surfaces that error rather than silently swallowing it.

set -euo pipefail

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

# Source .env for GITEA_TOKEN if present
for env_file in "$REPO_ROOT/.env" "$PWD/.env" "./.env"; do
  if [ -f "$env_file" ]; then
    set -a
    # shellcheck disable=SC1090
    . "$env_file"
    set +a
    break
  fi
done

# --- gitea repo resolution ------------------------------------------------
# REPO is the tea-CLI repo slug (owner/repo). tea resolves login from its
# config (~/.config/tea/config.yml) and the repo slug from --repo.
REPO="${GITEA_OWNER:-coreci}/${GITEA_REPO:-orca}"

# --- helpers --------------------------------------------------------------

err() { echo "release: error: $*" >&2; exit 1; }
info() { echo "release: $*"; }

require_tool() {
  command -v "$1" >/dev/null 2>&1 || err "required tool not found: $1"
}

# --- preflight ------------------------------------------------------------

require_tool git
require_tool go
require_tool tar

if [ -z "${GITEA_TOKEN:-}" ]; then
  err "GITEA_TOKEN is not set. Export it or put it in .env"
fi

if ! command -v tea >/dev/null 2>&1; then
  err "tea CLI not found on PATH. Install from https://gitea.com/gitea/tea"
fi

# --- version detection ----------------------------------------------------

VERSION="${1:-}"
if [ -z "$VERSION" ]; then
  VERSION="$(git describe --tags --abbrev=0 2>/dev/null || echo dev)"
fi
# Strip leading 'v' for the tarball name (we keep it in the release tag itself)
VERSION_NUMBER="${VERSION#v}"

info "version: $VERSION"
info "building..."

# --- build with version injection ----------------------------------------
# Cross-build linux-amd64 regardless of host arch (D-193). The install.sh
# user base is amd64; the .coreci.yml release step hardcodes the amd64
# tarball name. Building for the host arch produced the wrong tarball when
# the release was cut from an arm64 dev machine — the root cause of the
# v0.4.5 install incident (REQ-097).

GIT_COMMIT="$(git rev-parse --short HEAD)"
BUILD_TIME="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
LDFLAGS="-s -w -X git.cloudinit.dev/coreci/orca/internal/cli.version=$VERSION -X git.cloudinit.dev/coreci/orca/internal/cli.gitCommit=$GIT_COMMIT -X git.cloudinit.dev/coreci/orca/internal/cli.buildTime=$BUILD_TIME"

mkdir -p bin
info "building orca-${VERSION}-linux-amd64 (cross-compile, CGO_ENABLED=0)..."
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -ldflags="$LDFLAGS" -o bin/orca ./cmd/orca
info "built: bin/orca (linux-amd64)"

# --- tarball --------------------------------------------------------------
# Always produce the linux-amd64 tarball name that install.sh looks for.
# (D-193: arm64 is a separate enhancement; this milestone ships amd64 only.)

TARBALL="orca-${VERSION}-linux-amd64.tar.gz"
tar -czf "$TARBALL" -C bin orca
info "packaged: $TARBALL ($(du -h "$TARBALL" | cut -f1))"

# --- release notes from ---ci--- blocks ----------------------------------

NOTES_FILE="$(mktemp)"
trap 'rm -f "$NOTES_FILE"' EXIT

{
  echo "# Release $VERSION"
  echo ""
  echo "_Built: $BUILD_TIME from $GIT_COMMIT"
  echo ""

  PREV_TAG="$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")"
  if [ -n "$PREV_TAG" ]; then
    RANGE="$PREV_TAG..HEAD"
  else
    RANGE="HEAD"
  fi

  echo "## Changes since $PREV_TAG"
  echo ""
  # Extract messages of ---ci--- tagged commits in the range
  git log --pretty=format:'- %s' "$RANGE" 2>/dev/null | head -100 || true
  echo ""
} > "$NOTES_FILE"

info "release notes: $NOTES_FILE"
cat "$NOTES_FILE"

# --- publish to gitea -----------------------------------------------------

info "creating gitea release..."
tea releases create "$VERSION" \
  --repo "$REPO" \
  --title "Orca $VERSION" \
  --note-file "$NOTES_FILE" \
  --asset "$TARBALL"

# --- post-create asset verification (REQ-097, gate C-21) ------------------
# tea releases create has been observed to exit 0 without attaching the
# asset in some versions. Verify the asset actually appears in the release
# via the Gitea API; retry once if missing; fail loudly if still missing.
# This is the root-cause fix for the v0.8.x releases that shipped with zero
# binary assets.

verify_asset() {
  local tag="$1" want="$2"
  curl -fsSL "${GITEA_URL:-https://git.cloudinit.dev}/api/v1/repos/${GITEA_OWNER:-coreci}/${GITEA_REPO:-orca}/releases/tags/${tag}" \
    | sed -n 's/.*"name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' \
    | grep -qx "$want"
}

info "verifying asset ${TARBALL} attached to release ${VERSION}..."
if verify_asset "$VERSION" "$TARBALL"; then
  info "✓ asset verified: ${TARBALL}"
else
  info "asset missing after tea releases create; retrying upload..."
  # Retry: re-add the asset via tea releases edit
  tea release edit "$VERSION" --repo "$REPO" --asset "$TARBALL" 2>/dev/null \
    || tea releases edit "$VERSION" --repo "$REPO" --asset "$TARBALL" 2>/dev/null \
    || true
  sleep 2
  if verify_asset "$VERSION" "$TARBALL"; then
    info "✓ asset verified on retry: ${TARBALL}"
  else
    err "asset ${TARBALL} NOT attached to release ${VERSION} after retry — the release exists but has no binary. Run 'tea releases edit ${VERSION} --repo $REPO --asset $TARBALL' manually. (REQ-097, C-21)"
  fi
fi

info "✓ release $VERSION published with binary asset"

# --- publish container image to gitea registry (REQ-046) ------------------
# Skipped gracefully if docker is not on PATH (e.g. local dev without docker).
# The .coreci.yml release pipeline has a dedicated container-publish step
# that runs in a docker:24-cli image with docker-in-docker.

CONTAINER_REGISTRY="${CONTAINER_REGISTRY:-git.cloudinit.dev}"
CONTAINER_OWNER="${CONTAINER_OWNER:-coreci}"
CONTAINER_IMAGE="${CONTAINER_IMAGE:-orca}"
IMAGE="${CONTAINER_REGISTRY}/${CONTAINER_OWNER}/${CONTAINER_IMAGE}"

if ! command -v docker >/dev/null 2>&1; then
  info "docker not found on PATH — skipping container image publish (CI handles it)."
else
  info "building container image ${IMAGE}:${VERSION}..."
  docker build \
    --build-arg VERSION="$VERSION" \
    --build-arg GIT_COMMIT="$GIT_COMMIT" \
    --build-arg BUILD_TIME="$BUILD_TIME" \
    -t "${IMAGE}:${VERSION}" \
    -t "${IMAGE}:latest" \
    "$REPO_ROOT"

  if [ -z "${GITEA_TOKEN:-}" ]; then
    info "GITEA_TOKEN not set — skipping docker push (image built locally only)."
  else
    info "logging in to ${CONTAINER_REGISTRY}..."
    echo "$GITEA_TOKEN" | docker login "$CONTAINER_REGISTRY" -u cloudinit-bot --password-stdin
    info "pushing ${IMAGE}:${VERSION}..."
    docker push "${IMAGE}:${VERSION}"
    info "pushing ${IMAGE}:latest..."
    docker push "${IMAGE}:latest"
    docker logout "$CONTAINER_REGISTRY"
    info "✓ container image ${IMAGE}:${VERSION} published"
  fi
fi
