#!/usr/bin/env bash
# ──────────────────────────────────────────────────────────────────────────────
# release/scripts/tag-and-push.sh
#
# Creates an annotated git tag, optionally pushes it to origin, and optionally
# builds + pushes Docker images. Respects DRY_RUN to simulate all actions
# without actually executing them.
#
# Required environment:
#   NEW_VERSION     Semver string without prefix (e.g. "1.3.0")
#   TAG_PREFIX      Git tag prefix (default: "v")
#
# Optional environment:
#   DRY_RUN         "true" to skip all write operations (default: "false")
#   PUSH_DOCKER     "true" to build and push Docker images (default: "false")
#   DOCKER_REGISTRY Docker registry prefix (default: "ghcr.io/slthomason")
#   GIT_REMOTE      Remote to push to (default: "origin")
# ──────────────────────────────────────────────────────────────────────────────
set -euo pipefail

GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'

# ── Resolve parameters ─────────────────────────────────────────────────────────
NEW_VERSION="${NEW_VERSION:?'NEW_VERSION must be set (e.g. 1.3.0)'}"
TAG_PREFIX="${TAG_PREFIX:-v}"
DRY_RUN="${DRY_RUN:-false}"
PUSH_DOCKER="${PUSH_DOCKER:-false}"
DOCKER_REGISTRY="${DOCKER_REGISTRY:-ghcr.io/slthomason}"
GIT_REMOTE="${GIT_REMOTE:-origin}"

FULL_TAG="${TAG_PREFIX}${NEW_VERSION}"
DOCKER_IMAGE="${DOCKER_REGISTRY}/openmono-agent"

# ── Helpers ────────────────────────────────────────────────────────────────────
dry_prefix() { [[ "$DRY_RUN" == "true" ]] && echo "[DRY RUN] " || echo ""; }

run_or_dry() {
    local desc="$1"; shift
    local cmd=("$@")
    if [[ "$DRY_RUN" == "true" ]]; then
        printf "  ${CYAN}[DRY RUN]${NC} Would run: %s\n" "${cmd[*]}"
    else
        printf "  ${BOLD}Running:${NC} %s\n" "${cmd[*]}"
        "${cmd[@]}"
    fi
}

ok()   { printf "  ${GREEN}✔${NC}  %s\n" "$1"; }
warn() { printf "  ${YELLOW}⚠${NC}  %s\n" "$1"; }
err()  { printf "  ${RED}✘${NC}  %s\n" "$1" >&2; }
sep()  { printf "${BOLD}%s${NC}\n" "──────────────────────────────────────────"; }

# ── Header ─────────────────────────────────────────────────────────────────────
printf "\n${BOLD}Tag and Push — OpenMono.ai Release${NC}\n"
[[ "$DRY_RUN" == "true" ]] && printf "${YELLOW}(DRY RUN — no changes will be made)${NC}\n"
printf "\n"
printf "  Tag        : %s\n" "$FULL_TAG"
printf "  Remote     : %s\n" "$GIT_REMOTE"
printf "  Docker     : %s\n" "$([[ "$PUSH_DOCKER" == "true" ]] && echo "$DOCKER_IMAGE:$NEW_VERSION" || echo "disabled")"
printf "  Dry run    : %s\n" "$DRY_RUN"
echo ""

# ── Guard: tag must not already exist ─────────────────────────────────────────
sep
printf "${BOLD}[1/5] Validate tag uniqueness${NC}\n"

if git tag --list "$FULL_TAG" | grep -qx "$FULL_TAG"; then
    err "Tag '$FULL_TAG' already exists. Delete it first or bump the version again."
    exit 1
fi
ok "Tag '$FULL_TAG' does not exist yet"

# ── Guard: working tree must be clean ─────────────────────────────────────────
sep
printf "${BOLD}[2/5] Validate clean working tree${NC}\n"

if [[ -n "$(git status --porcelain)" ]]; then
    err "Working tree is dirty. Commit or stash all changes before tagging."
    git status --short | head -10 | sed 's/^/     /' >&2
    exit 1
fi
ok "Working tree is clean"

# ── Read changelog excerpt for tag message ─────────────────────────────────────
sep
printf "${BOLD}[3/5] Build tag annotation${NC}\n"

TAG_MSG_FILE=$(mktemp /tmp/openmono-tagmsg-XXXXXX.txt)
trap 'rm -f "$TAG_MSG_FILE"' EXIT

{
    printf "OpenMono.ai %s\n\n" "$FULL_TAG"
    if [[ -f CHANGELOG.md ]]; then
        # Extract the section for this version from CHANGELOG.md
        awk "/^## \[?${FULL_TAG}\]?/{found=1; next} found && /^## /{exit} found{print}" CHANGELOG.md \
            | head -30
    else
        printf "Release %s\n" "$FULL_TAG"
        printf "\nGenerated by OpenMono.ai release playbook.\n"
    fi
    printf "\nReleased: %s\n" "$(date -u '+%Y-%m-%dT%H:%M:%SZ')"
} > "$TAG_MSG_FILE"

ok "Tag annotation built ($(wc -l < "$TAG_MSG_FILE") lines)"
printf "\n  Preview:\n"
head -5 "$TAG_MSG_FILE" | sed 's/^/    /'
echo ""

# ── Create annotated tag ───────────────────────────────────────────────────────
sep
printf "${BOLD}[4/5] Create git tag${NC}\n"

run_or_dry "create tag" git tag -a "$FULL_TAG" -F "$TAG_MSG_FILE"

if [[ "$DRY_RUN" != "true" ]]; then
    ok "Tag created: $FULL_TAG"
fi

# Push tag to remote
run_or_dry "push tag" git push "$GIT_REMOTE" "$FULL_TAG"

if [[ "$DRY_RUN" != "true" ]]; then
    ok "Tag pushed to $GIT_REMOTE"
fi

# ── Optional: Docker build and push ───────────────────────────────────────────
sep
printf "${BOLD}[5/5] Docker image${NC}\n"

if [[ "$PUSH_DOCKER" != "true" ]]; then
    ok "Docker push disabled (set PUSH_DOCKER=true to enable)"
else
    DOCKERFILE="docker/Dockerfile.agent"
    if [[ ! -f "$DOCKERFILE" ]]; then
        warn "Dockerfile not found at $DOCKERFILE — skipping Docker build"
    else
        # Build
        run_or_dry "docker build" \
            docker build \
                --file "$DOCKERFILE" \
                --tag "${DOCKER_IMAGE}:${NEW_VERSION}" \
                --tag "${DOCKER_IMAGE}:latest" \
                --build-arg VERSION="$NEW_VERSION" \
                --label "org.opencontainers.image.version=$NEW_VERSION" \
                --label "org.opencontainers.image.created=$(date -u '+%Y-%m-%dT%H:%M:%SZ')" \
                --label "org.opencontainers.image.revision=$(git rev-parse HEAD)" \
                .

        if [[ "$DRY_RUN" != "true" ]]; then
            ok "Docker image built: ${DOCKER_IMAGE}:${NEW_VERSION}"
        fi

        # Push versioned tag
        run_or_dry "docker push (versioned)" \
            docker push "${DOCKER_IMAGE}:${NEW_VERSION}"

        # Push latest
        run_or_dry "docker push (latest)" \
            docker push "${DOCKER_IMAGE}:latest"

        if [[ "$DRY_RUN" != "true" ]]; then
            ok "Docker images pushed to registry"
        fi
    fi
fi

# ── Summary ────────────────────────────────────────────────────────────────────
echo ""
sep
if [[ "$DRY_RUN" == "true" ]]; then
    printf "${YELLOW}${BOLD}Dry run complete — no changes were made.${NC}\n\n"
    printf "  Would have created tag : %s\n" "$FULL_TAG"
    printf "  Would have pushed to   : %s\n" "$GIT_REMOTE"
    [[ "$PUSH_DOCKER" == "true" ]] && printf "  Would have pushed image: %s\n" "${DOCKER_IMAGE}:${NEW_VERSION}"
else
    printf "${GREEN}${BOLD}Release complete!${NC}\n\n"
    printf "  Tag created  : %s\n" "$FULL_TAG"
    printf "  Pushed to    : %s\n" "$GIT_REMOTE"
    [[ "$PUSH_DOCKER" == "true" ]] && printf "  Docker image : %s\n" "${DOCKER_IMAGE}:${NEW_VERSION}"
fi
echo ""

exit 0
