#!/bin/bash
set -euo pipefail

cd "$(dirname "$0")/.."

BIN_NAME="muthr"
TARGET_ARCH="macos-arm64"
RUST_TARGET="aarch64-apple-darwin"
GITHUB_REPO="tappunk/muthr"

DRY_RUN=false
if [[ "${1:-}" == "--dry-run" ]]; then
  DRY_RUN=true
  shift
fi

BUMP="${1:-patch}"
NOTES="${2:-}"

echo "[PROC] Verifying deployment dependencies..."
for tool in cargo gh shasum tar awk git sed; do
  if ! command -v "$tool" >/dev/null 2>&1; then
    echo "[ERR] Required CLI tool '$tool' is missing."
    exit 1
  fi
done

if ! gh auth status >/dev/null 2>&1; then
  echo "[ERR] GitHub CLI is not authenticated. Run 'gh auth login'."
  exit 1
fi

if [[ ! "$BUMP" =~ ^(patch|minor|major)$ ]]; then
  echo "[ERR] Invalid bump type '$BUMP'. Use: patch, minor, or major"
  exit 1
fi

if [[ -n $(git ls-files --others --exclude-standard) ]]; then
  echo "[ERR] Untracked files found in workspace. Add or remove them before releasing."
  git ls-files --others --exclude-standard
  exit 1
fi

if [[ -n $(git status --porcelain) ]]; then
  echo "[ERR] Uncommitted changes detected. Stash or commit before releasing."
  exit 1
fi

if [[ $(git branch --show-current) != "main" ]]; then
  echo "[ERR] You must be on the 'main' branch to cut a release."
  exit 1
fi

git fetch origin
if [[ -n $(git log HEAD..origin/main --oneline) ]]; then
  echo "[ERR] Local 'main' is behind 'origin/main'. Pull latest changes first."
  exit 1
fi

echo "[PROC] Executing strict code quality gates..."
cargo fmt --check || {
  echo "[ERR] Code formatting violations found. Run 'cargo fmt'."
  exit 1
}
cargo clippy --all-targets --all-features -- -D warnings || {
  echo "[ERR] Clippy warnings detected. Fix them before releasing."
  exit 1
}
cargo test || {
  echo "[ERR] Test suite execution failed."
  exit 1
}
./scripts/smoke.sh || {
  echo "[ERR] GA smoke matrix failed."
  exit 1
}

CURRENT_VERSION=$(grep -m 1 '^version = ' Cargo.toml | sed 's/version = "\(.*\)"/\1/')
if [[ -z "$CURRENT_VERSION" ]]; then
  echo "[ERR] Could not read current version from Cargo.toml"
  exit 1
fi

IFS='.' read -r MAJOR MINOR PATCH <<<"$CURRENT_VERSION"
case "$BUMP" in
patch) PATCH=$((PATCH + 1)) ;;
minor)
  MINOR=$((MINOR + 1))
  PATCH=0
  ;;
major)
  MAJOR=$((MAJOR + 1))
  MINOR=0
  PATCH=0
  ;;
esac
NEW_VERSION="${MAJOR}.${MINOR}.${PATCH}"

echo "Preparing Apple Silicon Release: v$CURRENT_VERSION -> v$NEW_VERSION ($BUMP)"
if $DRY_RUN; then
  echo "[INFO] Dry run complete. Code is pristine and ready for release."
  exit 0
fi

BACKUP_CARGO_TOML=""
BACKUP_CARGO_LOCK=""
BACKUP_FLAKE_NIX=""
rollback() {
  echo ""
  echo "[CRIT] Release pipeline interrupted!"
  if git rev-parse "v$NEW_VERSION" >/dev/null 2>&1; then
    git tag -d "v$NEW_VERSION"
  fi
  if [[ -n "${BACKUP_CARGO_TOML:-}" && -f "$BACKUP_CARGO_TOML" ]]; then
    cp "$BACKUP_CARGO_TOML" Cargo.toml
  fi
  if [[ -n "${BACKUP_CARGO_LOCK:-}" && -f "$BACKUP_CARGO_LOCK" ]]; then
    cp "$BACKUP_CARGO_LOCK" Cargo.lock
  fi
  if [[ -n "${BACKUP_FLAKE_NIX:-}" && -f "$BACKUP_FLAKE_NIX" ]]; then
    cp "$BACKUP_FLAKE_NIX" flake.nix
  fi
  rm -f Cargo.toml.bak flake.nix.bak 2>/dev/null || true
  if [[ -n "${ARCHIVE_NAME:-}" ]]; then
    rm -f "$ARCHIVE_NAME"
  fi
  if [[ -n "${CHECKSUM_NAME:-}" ]]; then
    rm -f "$CHECKSUM_NAME"
  fi
  if [[ -n "${BACKUP_CARGO_TOML:-}" ]]; then
    rm -f "$BACKUP_CARGO_TOML"
  fi
  if [[ -n "${BACKUP_CARGO_LOCK:-}" ]]; then
    rm -f "$BACKUP_CARGO_LOCK"
  fi
  if [[ -n "${BACKUP_FLAKE_NIX:-}" ]]; then
    rm -f "$BACKUP_FLAKE_NIX"
  fi
  if [[ -n "${STAGING_DIR:-}" && -d "${STAGING_DIR}" ]]; then
    rm -rf "${STAGING_DIR}"
  fi
  echo "[WARN] Rolled back. Re-run release.sh to try again."
}
trap rollback ERR

echo "[PROC] Updating versioning configuration..."
BACKUP_CARGO_TOML=$(mktemp)
BACKUP_CARGO_LOCK=$(mktemp)
BACKUP_FLAKE_NIX=$(mktemp)
cp Cargo.toml "$BACKUP_CARGO_TOML"
cp Cargo.lock "$BACKUP_CARGO_LOCK"
cp flake.nix "$BACKUP_FLAKE_NIX"
sed -i.bak "s/^version = \"$CURRENT_VERSION\"$/version = \"$NEW_VERSION\"/" Cargo.toml
sed -i.bak "s/^\([[:space:]]*version = \"\)$CURRENT_VERSION\";/\1$NEW_VERSION\";/" flake.nix
rm Cargo.toml.bak flake.nix.bak

echo "[PROC] Compiling optimized release binary for Apple Silicon..."
cargo build --release --target "$RUST_TARGET"

echo "[PROC] Packaging distribution archives..."
ARCHIVE_NAME="${BIN_NAME}-${NEW_VERSION}-bin-${TARGET_ARCH}.tar.gz"
CHECKSUM_NAME="${ARCHIVE_NAME}.sha256"
STAGING_DIR="$(mktemp -d)"

mkdir -p "${STAGING_DIR}/${BIN_NAME}"
cp "target/${RUST_TARGET}/release/${BIN_NAME}" "${STAGING_DIR}/${BIN_NAME}/"
cp README.md LICENSE "${STAGING_DIR}/${BIN_NAME}/" 2>/dev/null || true

tar -czf "$ARCHIVE_NAME" -C "$STAGING_DIR" "${BIN_NAME}"
shasum -a 256 "$ARCHIVE_NAME" >"$CHECKSUM_NAME"
rm -rf "$STAGING_DIR"
rm -f "$BACKUP_CARGO_TOML" "$BACKUP_CARGO_LOCK" "$BACKUP_FLAKE_NIX"
BACKUP_CARGO_TOML=""
BACKUP_CARGO_LOCK=""
BACKUP_FLAKE_NIX=""

echo "[PROC] Recording version changes to Git history..."
git add Cargo.toml Cargo.lock flake.nix
git commit -m "chore: release v$NEW_VERSION [skip ci]"
git tag -a "v$NEW_VERSION" -m "Release v$NEW_VERSION"

trap - ERR

echo "[PROC] Synchronizing changes with remote origin..."
git push origin main
git push origin "v$NEW_VERSION"

echo "[PROC] Waiting for GitHub mirror to expose tag v$NEW_VERSION..."
MAX_TAG_WAIT_ATTEMPTS=30
TAG_WAIT_INTERVAL_SECS=2
for ((attempt = 1; attempt <= MAX_TAG_WAIT_ATTEMPTS; attempt++)); do
  if gh api "repos/${GITHUB_REPO}/git/ref/tags/v${NEW_VERSION}" >/dev/null 2>&1; then
    echo "[PROC] GitHub mirror now contains tag v$NEW_VERSION"
    break
  fi

  if [[ "$attempt" -eq "$MAX_TAG_WAIT_ATTEMPTS" ]]; then
    echo "[ERR] Timed out waiting for GitHub mirror tag v$NEW_VERSION in ${GITHUB_REPO}"
    echo "[ERR] Confirm mirror health or push tag directly to GitHub, then re-run release."
    exit 1
  fi

  sleep "$TAG_WAIT_INTERVAL_SECS"
done

echo "[PROC] Deploying GitHub Release and assets..."
if [[ -n "$NOTES" ]]; then
  gh release create "v$NEW_VERSION" "$ARCHIVE_NAME" "$CHECKSUM_NAME" \
    -R "$GITHUB_REPO" \
    --title "v$NEW_VERSION" \
    --notes "$NOTES"
else
  gh release create "v$NEW_VERSION" "$ARCHIVE_NAME" "$CHECKSUM_NAME" \
    -R "$GITHUB_REPO" \
    --title "v$NEW_VERSION" \
    --generate-notes
fi

echo "[PROC] Propagating release configuration to Homebrew tap..."
RAW_SHA=$(awk '{print $1}' "${CHECKSUM_NAME}")
TAP_DIR="$(mktemp -d)"

git clone --depth 1 "ssh://git@umbrel.local:2223/tappunk/homebrew-muthr.git" "$TAP_DIR"

cat <<EOF >"${TAP_DIR}/Formula/muthr.rb"
class Muthr < Formula
  desc "Zero-trust orchestrator for MLX inference, container-based sandboxes, and MCP services on Apple Silicon"
  homepage "https://github.com/tappunk/muthr"
  version "${NEW_VERSION}"

  depends_on arch: :arm64
  depends_on :macos
  depends_on "lablup/tap/mlxcel"

  url "https://github.com/tappunk/muthr/releases/download/v#{version}/muthr-#{version}-bin-macos-arm64.tar.gz"
  sha256 "${RAW_SHA}"

  def install
    bin.install "muthr"
  end

  def caveats
    <<~EOS
      muthr configurations must be initialized before first execution. Run:
        muthr init

      Runtime prerequisite:
        Apple container CLI must be available on this host.
    EOS
  end

  test do
    assert_match version.to_s, shell_output("#{bin}/muthr --version")
  end
end
EOF

(
  cd "$TAP_DIR"
  git add Formula/muthr.rb
  git commit -m "chore(formula): bump muthr to v${NEW_VERSION}"
  git push origin main
)

echo "[PROC] Waiting for GitHub mirror to propagate tap formula v$NEW_VERSION..."
MAX_TAP_WAIT_ATTEMPTS=30
TAP_WAIT_INTERVAL_SECS=2
for ((attempt = 1; attempt <= MAX_TAP_WAIT_ATTEMPTS; attempt++)); do
  TAP_FORMULA_RAW="$(gh api "repos/tappunk/homebrew-muthr/contents/Formula/muthr.rb" -H "Accept: application/vnd.github.raw" 2>/dev/null || true)"
  TAP_VERSION_CHECK="$(printf '%s\n' "$TAP_FORMULA_RAW" | awk -F'"' '/^  version "/ { print $2; exit }')"
  if [[ "$TAP_VERSION_CHECK" == "$NEW_VERSION" ]]; then
    echo "[PROC] GitHub mirror now contains tap formula v$NEW_VERSION"
    break
  fi

  if [[ "$attempt" -eq "$MAX_TAP_WAIT_ATTEMPTS" ]]; then
    echo "[ERR] Timed out waiting for GitHub mirror to propagate tap formula v$NEW_VERSION"
    echo "[ERR] Confirm mirror health or push directly, then re-run validation manually."
    exit 1
  fi

  sleep "$TAP_WAIT_INTERVAL_SECS"
done

echo "[PROC] Validating Homebrew tap version and checksum..."
TAP_FORMULA_RAW="$(gh api "repos/tappunk/homebrew-muthr/contents/Formula/muthr.rb" -H "Accept: application/vnd.github.raw")"
TAP_VERSION="$(printf '%s\n' "$TAP_FORMULA_RAW" | awk -F'"' '/^  version "/ { print $2; exit }')"
TAP_SHA="$(printf '%s\n' "$TAP_FORMULA_RAW" | awk -F'"' '/^  sha256 "/ { print $2; exit }')"

if [[ "$TAP_VERSION" != "$NEW_VERSION" ]]; then
  echo "[ERR] Homebrew tap formula version mismatch: expected ${NEW_VERSION}, found ${TAP_VERSION:-<empty>}"
  exit 1
fi

if [[ "$TAP_SHA" != "$RAW_SHA" ]]; then
  echo "[ERR] Homebrew tap formula checksum mismatch: expected ${RAW_SHA}, found ${TAP_SHA:-<empty>}"
  exit 1
fi

echo "[PROC] Homebrew tap formula matches release v$NEW_VERSION"
rm -rf "$TAP_DIR"

echo "[PROC] Synchronizing local Homebrew tap mirror..."
LOCAL_TAP_DIR="${HOME}/src/homebrew-muthr"
if [[ ! -d "${LOCAL_TAP_DIR}/.git" ]]; then
  echo "[WARN] Skipping local tap sync. Repository not found at ${LOCAL_TAP_DIR}."
elif [[ -n $(git -C "${LOCAL_TAP_DIR}" status --porcelain) ]]; then
  echo "[WARN] Skipping local tap sync. Uncommitted changes in ${LOCAL_TAP_DIR}."
elif [[ $(git -C "${LOCAL_TAP_DIR}" branch --show-current) != "main" ]]; then
  echo "[WARN] Skipping local tap sync. ${LOCAL_TAP_DIR} is not on 'main'."
elif ! git -C "${LOCAL_TAP_DIR}" fetch origin >/dev/null 2>&1; then
  echo "[WARN] Skipping local tap sync. Failed to fetch origin in ${LOCAL_TAP_DIR}."
elif [[ -n $(git -C "${LOCAL_TAP_DIR}" log HEAD..origin/main --oneline) ]]; then
  if git -C "${LOCAL_TAP_DIR}" pull --ff-only >/dev/null 2>&1; then
    echo "[PROC] Local tap mirror synchronized: ${LOCAL_TAP_DIR}"
  else
    echo "[WARN] Skipping local tap sync. Fast-forward pull failed in ${LOCAL_TAP_DIR}."
  fi
else
  echo "[PROC] Local tap mirror already up to date: ${LOCAL_TAP_DIR}"
fi

echo "[PROC] Cleaning up local packaging assets..."
rm -f "$ARCHIVE_NAME" "$CHECKSUM_NAME"

echo "[PROC] Publishing crate package to crates.io..."
cargo publish

echo "[ SUCCESS ] Release v$NEW_VERSION fully deployed!"

if [[ -t 0 && -d "${HOME}/src/homepage/.git" ]]; then
  echo ""
  echo "[INFO] Do you want to publish the homepage (VitePress docs) to homepage-live?"
  echo "       This will deploy updated docs to https://tappunk.com/muthr/"
  printf "Publish homepage? [y/N]: "
  read -r answer
  if [[ "${answer:-n}" =~ ^[Yy] ]]; then
    echo "[PROC] Publishing homepage..."
    if "${HOME}/src/homepage/scripts/publish.sh"; then
      echo "[SUCCESS] Homepage published."
    else
      echo "[WARN] Homepage publish failed. Review output above."
    fi
  fi
fi
