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

usage() {
  cat <<'EOF' >&2
usage: agentteam-prod-build-release.sh [--build-only] [artifact-dir]

Build a production release bundle locally and, by default, activate it immediately.
The release bundle includes the unified AgentTeam Server, one-shot tools, and web assets.
This script always emits:
  - release-id
  - bundle path
  - checksums.txt path

If [artifact-dir] is omitted, artifacts are written to:
  .artifacts/prod/<release-id>

Environment overrides:
  AGENTTEAM_PROD_RELEASE_ID            explicit release id (default: <timestamp>-<git short sha>)
  AGENTTEAM_PROD_ARTIFACT_DIR          artifact directory when positional arg is omitted
  AGENTTEAM_PROD_BUILD_ONLY            set to 1/true/yes to skip activation
  AGENTTEAM_PROD_BUILD_RELEASE_SCRIPT  wrapper around scripts/release/build-release.sh
  AGENTTEAM_PROD_ACTIVATE_RELEASE_SCRIPT  deploy helper (default: scripts/agentteam-prod-activate-release.sh)
  AGENTTEAM_PROD_ENVIRONMENT           activation environment (default: staging)
  AGENTTEAM_PROD_GOOS                  target OS for production bundle (default: linux)
  AGENTTEAM_PROD_GOARCH                target architecture for production bundle (default: amd64)
  AGENTTEAM_DEV_FEATURES                frontend build features; MESHX is always added for production
  AGENTTEAM_DAEMON_MIN_VERSION            optional daemon hard gate persisted into the release metadata
EOF
}

fail() {
  printf '%s\n' "$*" >&2
  exit 1
}

on_error() {
  local exit_code="$?"
  local line="$1"
  local cmd="$2"
  fail "agentteam prod build release failed at line ${line}: ${cmd} (exit=${exit_code})"
}

trap 'on_error ${LINENO} "${BASH_COMMAND}"' ERR

require_command() {
  local cmd="$1"
  command -v "$cmd" >/dev/null 2>&1 || fail "missing required command: $cmd"
}

require_file() {
  local path="$1"
  [[ -f "$path" ]] || fail "required file not found: $path"
}

append_dev_feature() {
  local raw="$1"
  local feature="$2"
  local normalized_feature
  normalized_feature="$(printf '%s' "$feature" | tr '[:lower:]' '[:upper:]')"

  for value in ${raw//,/ }; do
    if [[ "$(printf '%s' "$value" | tr '[:lower:]' '[:upper:]')" == "$normalized_feature" ]]; then
      printf '%s' "$raw"
      return 0
    fi
  done

  if [[ -n "$raw" ]]; then
    printf '%s,%s' "$raw" "$feature"
  else
    printf '%s' "$feature"
  fi
}

validate_release_env_value() {
  local key="$1"
  local value="$2"

  [[ "$value" != *$'\n'* ]] || fail "${key} must not contain newlines"
  [[ "$value" =~ ^[[:alnum:]/.+-]*$ ]] || fail "${key} must contain only semver-safe characters"
}

maybe_embed_release_env() {
  local bundle_path="$1"

  if [[ "${AGENTTEAM_DAEMON_MIN_VERSION+x}" != x ]]; then
    return 0
  fi

  local daemon_min_version="${AGENTTEAM_DAEMON_MIN_VERSION:-}"
  validate_release_env_value "AGENTTEAM_DAEMON_MIN_VERSION" "$daemon_min_version"

  local temp_dir
  temp_dir="$(mktemp -d "${TMPDIR:-/tmp}/agentteam-prod-release.XXXXXX")"
  tar -xzf "$bundle_path" -C "$temp_dir"
  printf 'AGENTTEAM_DAEMON_MIN_VERSION=%s\n' "$daemon_min_version" >"$temp_dir/release.env"
  tar -C "$temp_dir" -czf "$bundle_path" .
  rm -rf "$temp_dir"
}

readonly SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
readonly REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
readonly DEFAULT_BUILD_SCRIPT="$REPO_ROOT/scripts/release/build-release.sh"
readonly DEFAULT_ACTIVATE_SCRIPT="$SCRIPT_DIR/agentteam-prod-activate-release.sh"

require_command bash
require_command date
require_command git
require_command mkdir
require_command mktemp
require_command sha256sum
require_command tar

build_only="${AGENTTEAM_PROD_BUILD_ONLY:-}"
if [[ "$build_only" == "1" || "$build_only" == "true" || "$build_only" == "yes" ]]; then
  build_only=1
else
  build_only=0
fi

artifact_dir_arg=''
while [[ $# -gt 0 ]]; do
  case "$1" in
    --build-only)
      build_only=1
      shift
      ;;
    --help|-h)
      usage
      exit 0
      ;;
    --*)
      usage
      exit 1
      ;;
    *)
      if [[ -n "$artifact_dir_arg" ]]; then
        usage
        exit 1
      fi
      artifact_dir_arg="$1"
      shift
      ;;
  esac
done

build_release_script="${AGENTTEAM_PROD_BUILD_RELEASE_SCRIPT:-$DEFAULT_BUILD_SCRIPT}"
require_file "$build_release_script"
activate_release_script="${AGENTTEAM_PROD_ACTIVATE_RELEASE_SCRIPT:-$DEFAULT_ACTIVATE_SCRIPT}"
if [[ "$build_only" != "1" ]]; then
  require_file "$activate_release_script"
fi

if [[ -n "${AGENTTEAM_PROD_RELEASE_ID:-}" ]]; then
  release_id="$AGENTTEAM_PROD_RELEASE_ID"
else
  release_id="$(date +%Y%m%d%H%M%S)-$(git -C "$REPO_ROOT" rev-parse --short HEAD)"
fi
[[ -n "$release_id" ]] || fail "release id must not be empty"

if [[ -n "$artifact_dir_arg" ]]; then
  artifact_dir="$artifact_dir_arg"
elif [[ -n "${AGENTTEAM_PROD_ARTIFACT_DIR:-}" ]]; then
  artifact_dir="$AGENTTEAM_PROD_ARTIFACT_DIR"
else
  artifact_dir="$REPO_ROOT/.artifacts/prod/$release_id"
fi

target_goos="${AGENTTEAM_PROD_GOOS:-linux}"
target_goarch="${AGENTTEAM_PROD_GOARCH:-amd64}"
frontend_dev_features="$(append_dev_feature "${AGENTTEAM_DEV_FEATURES:-}" "MESHX")"

bundle_path="$artifact_dir/agentteam-release-$release_id.tar.gz"
checksum_path="$artifact_dir/checksums.txt"
release_id_path="$artifact_dir/release-id.txt"

mkdir -p "$artifact_dir"

AGENTTEAM_RELEASE_GOOS="$target_goos" \
AGENTTEAM_RELEASE_GOARCH="$target_goarch" \
AGENTTEAM_RELEASE_ARCHIVE_PATH="$bundle_path" \
AGENTTEAM_DEV_FEATURES="$frontend_dev_features" \
  bash "$build_release_script"
[[ -f "$bundle_path" ]] || fail "release bundle was not created: $bundle_path"
maybe_embed_release_env "$bundle_path"

sha256sum "$bundle_path" >"$checksum_path"
printf '%s\n' "$release_id" >"$release_id_path"

cat <<EOF
release_id=$release_id
artifact_dir=$artifact_dir
release_id_path=$release_id_path
bundle_path=$bundle_path
checksum_path=$checksum_path
EOF

if [[ "$build_only" == "1" ]]; then
  exit 0
fi

AGENTTEAM_PROD_ENVIRONMENT="${AGENTTEAM_PROD_ENVIRONMENT:-staging}" \
  bash "$activate_release_script" "$bundle_path" "$checksum_path" "$release_id"
