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

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

DELIVERY_REMOTE_URL="https://github.com/yueyue27418/1688-autoprocurement.git"
DELIVERY_TAG=""
ENV_FILE="$ROOT_DIR/.env"
OUTPUT_DIR="$ROOT_DIR/dist"
NAME="1688-autoprocurement-pulse"
DRY_RUN=0
FETCH_SOURCE=1

usage() {
  cat <<'EOF'
Usage:
  bash scripts/build-delivery-bundle.sh [options]

Options:
  --tag TAG          Delivery repository tag to package. Defaults to the latest version-sorted delivery tag.
  --env-file PATH    Env file to inject as deploy/env/.env. Defaults to .env.
  --output-dir DIR   Directory for the generated tarball. Defaults to dist.
  --name NAME        Package name prefix. Defaults to 1688-autoprocurement-pulse.
  --no-fetch         Use local tags only; useful for tests.
  --dry-run          Print the artifact plan without creating files.
  -h, --help         Show this help.

The source is the delivery repository tag. Without --tag, the latest version-sorted tag is used.
EOF
}

log() {
  printf '[bundle] %s\n' "$*"
}

die() {
  printf '[bundle] ERROR: %s\n' "$*" >&2
  exit 1
}

safe_filename_component() {
  local value="$1"
  value="$(printf '%s' "$value" | sed -E 's#[^A-Za-z0-9._-]+#-#g; s#^-+##; s#-+$##')"
  [[ -n "$value" ]] || value="tag"
  printf '%s' "$value"
}

run_cmd() {
  if [[ "$DRY_RUN" -eq 1 ]]; then
    printf '[bundle] DRY-RUN:'
    printf ' %q' "$@"
    printf '\n'
    return
  fi

  "$@"
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    --)
      ;;
    --ref|--remote-url|--source-ref)
      die "Bundle source is fixed to delivery repository tags; use --tag to choose a delivery tag."
      ;;
    --tag)
      shift
      [[ $# -gt 0 ]] || die "--tag requires a value."
      DELIVERY_TAG="$1"
      ;;
    --env-file)
      shift
      [[ $# -gt 0 ]] || die "--env-file requires a path."
      ENV_FILE="$1"
      ;;
    --output-dir)
      shift
      [[ $# -gt 0 ]] || die "--output-dir requires a path."
      OUTPUT_DIR="$1"
      ;;
    --name)
      shift
      [[ $# -gt 0 ]] || die "--name requires a value."
      NAME="$1"
      ;;
    --no-fetch)
      FETCH_SOURCE=0
      ;;
    --dry-run)
      DRY_RUN=1
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      die "Unknown argument: $1"
      ;;
  esac
  shift
done

[[ -f "$ENV_FILE" ]] || die "Env file not found: $ENV_FILE"
git -C "$ROOT_DIR" rev-parse --is-inside-work-tree >/dev/null 2>&1 || die "Not inside a Git repository."

if [[ -z "$DELIVERY_TAG" ]]; then
  if [[ "$FETCH_SOURCE" -eq 1 ]]; then
    DELIVERY_TAG="$(git ls-remote --tags --refs "$DELIVERY_REMOTE_URL" 'v*' \
      | sed -E 's#.*refs/tags/##' \
      | sort -Vr \
      | head -n 1)"
  else
    DELIVERY_TAG="$(git -C "$ROOT_DIR" tag --list 'v*' --sort=-v:refname | head -n 1)"
  fi
  [[ -n "$DELIVERY_TAG" ]] || die "No delivery tags found. Publish with --delivery-tag first, or pass --tag."
fi

if [[ "$DRY_RUN" -eq 1 ]]; then
  SHORT_REF="$DELIVERY_TAG"
  FULL_REF="<resolved-from-delivery-tag>"
else
  if [[ "$FETCH_SOURCE" -eq 1 ]]; then
    TAG_REPO_DIR="$(mktemp -d)"
    trap 'rm -rf "$TAG_REPO_DIR"' EXIT
    git init -q "$TAG_REPO_DIR"
    git -C "$TAG_REPO_DIR" fetch --depth=1 "$DELIVERY_REMOTE_URL" "refs/tags/${DELIVERY_TAG}:refs/tags/${DELIVERY_TAG}"
  else
    TAG_REPO_DIR="$ROOT_DIR"
  fi

  git -C "$TAG_REPO_DIR" rev-parse --verify "refs/tags/${DELIVERY_TAG}^{commit}" >/dev/null 2>&1 \
    || die "Delivery tag not found: $DELIVERY_TAG"
  SHORT_REF="$(git -C "$TAG_REPO_DIR" rev-parse --short "refs/tags/${DELIVERY_TAG}^{commit}")"
  FULL_REF="$(git -C "$TAG_REPO_DIR" rev-parse "refs/tags/${DELIVERY_TAG}^{commit}")"
fi

SAFE_DELIVERY_TAG="$(safe_filename_component "$DELIVERY_TAG")"
if [[ "$DRY_RUN" -eq 1 ]]; then
  ARCHIVE_NAME="${NAME}-${SAFE_DELIVERY_TAG}.delivery.tar.gz"
else
  ARCHIVE_NAME="${NAME}-${SAFE_DELIVERY_TAG}-${SHORT_REF}.delivery.tar.gz"
fi
ARCHIVE_PATH="$OUTPUT_DIR/$ARCHIVE_NAME"

log "Packaging delivery tag $DELIVERY_TAG ($SHORT_REF)."
log "Artifact: $ARCHIVE_PATH"
log "Injecting env file as deploy/env/.env; env values are not printed."
log "Writing MANIFEST.txt with package metadata."

if [[ "$DRY_RUN" -eq 1 ]]; then
  log "Dry run complete. Planned artifact name ends with .delivery.tar.gz."
  exit 0
fi

TMP_DIR="$(mktemp -d)"
if [[ -n "${TAG_REPO_DIR:-}" && "$TAG_REPO_DIR" != "$ROOT_DIR" ]]; then
  trap 'rm -rf "$TMP_DIR" "$TAG_REPO_DIR"' EXIT
else
  trap 'rm -rf "$TMP_DIR"' EXIT
fi

mkdir -p "$OUTPUT_DIR" "$TMP_DIR/package"

git -C "$TAG_REPO_DIR" archive "$FULL_REF" | tar -x -C "$TMP_DIR/package"

mkdir -p "$TMP_DIR/package/deploy/env"
cp "$ENV_FILE" "$TMP_DIR/package/deploy/env/.env"
chmod 600 "$TMP_DIR/package/deploy/env/.env"

cat > "$TMP_DIR/package/MANIFEST.txt" <<EOF
name=$NAME
artifact_name=$ARCHIVE_NAME
source=delivery-tag
delivery_remote_url=$DELIVERY_REMOTE_URL
delivery_tag=$DELIVERY_TAG
commit=$FULL_REF
created_at=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
env_path=deploy/env/.env
EOF

tar -czf "$ARCHIVE_PATH" -C "$TMP_DIR/package" .
log "Created $ARCHIVE_PATH"
