#!/usr/bin/env bash
# =============================================================================
# Changemaker Lite V2 — Upgrade Check Script
# Checks for available updates and writes status to data/upgrade/status.json.
# Safe to run via cron or on-demand via file trigger.
# Usage: ./scripts/upgrade-check.sh [--branch BRANCH]
# =============================================================================
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
UPGRADE_DIR="${PROJECT_DIR}/data/upgrade"
STATUS_FILE="${UPGRADE_DIR}/status.json"
BRANCH=""

# --- Parse Arguments ---
while [[ $# -gt 0 ]]; do
  case "$1" in
    --branch) BRANCH="$2"; shift 2 ;;
    *) shift ;;
  esac
done

cd "$PROJECT_DIR"
mkdir -p "$UPGRADE_DIR"

# --- Detect install mode ---
if [[ -f "$PROJECT_DIR/VERSION" ]] && [[ ! -d "$PROJECT_DIR/.git" ]]; then
  INSTALL_MODE="release"
else
  INSTALL_MODE="source"
fi

# --- Release mode: check Gitea Releases API ---
if [[ "$INSTALL_MODE" == "release" ]]; then
  GITEA_API="https://gitea.bnkops.com/api/v1"
  CURRENT_VERSION=$(head -1 "$PROJECT_DIR/VERSION" 2>/dev/null || echo "unknown")
  CURRENT_SHA=$(sed -n '2p' "$PROJECT_DIR/VERSION" 2>/dev/null || echo "unknown")
  CURRENT_DATE=$(sed -n '3p' "$PROJECT_DIR/VERSION" 2>/dev/null || echo "")

  RELEASE_JSON=$(curl -sf "${GITEA_API}/repos/admin/changemaker.lite/releases/latest" 2>/dev/null || true)
  if [[ -z "$RELEASE_JSON" ]]; then
    cat > "$STATUS_FILE" <<EOF
{
  "branch": "release",
  "currentCommit": "${CURRENT_SHA}",
  "currentCommitFull": "${CURRENT_SHA}",
  "currentMessage": "Release ${CURRENT_VERSION}",
  "currentDate": "${CURRENT_DATE}",
  "remoteCommit": null,
  "commitsBehind": 0,
  "changelog": [],
  "checkedAt": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "error": "Failed to reach Gitea API"
}
EOF
    exit 1
  fi

  LATEST_TAG=$(echo "$RELEASE_JSON" | python3 -c "import sys,json; print(json.load(sys.stdin).get('tag_name',''))" 2>/dev/null)
  LATEST_DATE=$(echo "$RELEASE_JSON" | python3 -c "import sys,json; print(json.load(sys.stdin).get('created_at',''))" 2>/dev/null)
  LATEST_BODY=$(echo "$RELEASE_JSON" | python3 -c "import sys,json; print(json.load(sys.stdin).get('body','').replace('\"','\\\\\"')[:200])" 2>/dev/null)

  # Breaking-release marker: first line of the release body matching
  # `^BREAKING:[[:space:]]*(.+)` (case-insensitive) flags this release as
  # requiring manual confirmation. Admin UI gates Start Upgrade and
  # auto-upgrade refuses to apply until the operator confirms.
  IS_BREAKING=$(echo "$RELEASE_JSON" | python3 -c "
import sys, json, re
body = json.load(sys.stdin).get('body', '') or ''
m = re.match(r'^BREAKING:\s*(.+?)(?:\n|$)', body, re.IGNORECASE)
print('true' if m else 'false')
" 2>/dev/null || echo "false")
  BREAKING_REASON=$(echo "$RELEASE_JSON" | python3 -c "
import sys, json, re
body = json.load(sys.stdin).get('body', '') or ''
m = re.match(r'^BREAKING:\s*(.+?)(?:\n|$)', body, re.IGNORECASE)
print((m.group(1).strip() if m else '').replace('\"','\\\\\"')[:300])
" 2>/dev/null || echo "")

  if [[ "$CURRENT_VERSION" == "$LATEST_TAG" ]]; then
    COMMITS_BEHIND=0
  else
    COMMITS_BEHIND=1
  fi

  cat > "$STATUS_FILE" <<EOF
{
  "branch": "release",
  "currentCommit": "${CURRENT_SHA}",
  "currentCommitFull": "${CURRENT_SHA}",
  "currentMessage": "Release ${CURRENT_VERSION}",
  "currentDate": "${CURRENT_DATE}",
  "remoteCommit": "${LATEST_TAG}",
  "remoteCommitFull": "${LATEST_TAG}",
  "commitsBehind": ${COMMITS_BEHIND},
  "changelog": [{"hash":"${LATEST_TAG}","message":"${LATEST_BODY}","date":"${LATEST_DATE}","author":"release"}],
  "breaking": ${IS_BREAKING},
  "breakingReason": "${BREAKING_REASON}",
  "checkedAt": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "error": null
}
EOF
  echo "Update check complete (release mode): ${CURRENT_VERSION} → ${LATEST_TAG} (${COMMITS_BEHIND} update(s) available)"
  exit 0
fi

# --- Source mode: git-based check ---

# Determine branch
if [[ -z "$BRANCH" ]]; then
  BRANCH="$(git rev-parse --abbrev-ref HEAD)"
fi

# Write an error status and exit
write_error() {
  local msg="$1"
  cat > "$STATUS_FILE" <<EOF
{
  "branch": "${BRANCH}",
  "currentCommit": "$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")",
  "currentCommitFull": "$(git rev-parse HEAD 2>/dev/null || echo "unknown")",
  "currentMessage": "$(git log -1 --format='%s' HEAD 2>/dev/null | sed 's/"/\\"/g' || echo "")",
  "currentDate": "$(git log -1 --format='%aI' HEAD 2>/dev/null || echo "")",
  "remoteCommit": null,
  "commitsBehind": 0,
  "changelog": [],
  "checkedAt": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "error": "${msg}"
}
EOF
  exit 1
}

# Fetch latest from remote
if ! timeout 30 git fetch origin "$BRANCH" 2>/dev/null; then
  write_error "Failed to reach git remote"
fi

# Gather info
CURRENT_COMMIT="$(git rev-parse HEAD)"
CURRENT_SHORT="$(git rev-parse --short HEAD)"
CURRENT_MSG="$(git log -1 --format='%s' HEAD | sed 's/"/\\"/g')"
CURRENT_DATE="$(git log -1 --format='%aI' HEAD)"
REMOTE_COMMIT="$(git rev-parse "origin/${BRANCH}" 2>/dev/null || echo "")"
REMOTE_SHORT="$(git rev-parse --short "origin/${BRANCH}" 2>/dev/null || echo "")"

if [[ -z "$REMOTE_COMMIT" ]]; then
  write_error "Remote branch origin/${BRANCH} not found"
fi

# Count commits behind
COMMITS_BEHIND=0
if [[ "$CURRENT_COMMIT" != "$REMOTE_COMMIT" ]]; then
  COMMITS_BEHIND="$(git rev-list --count HEAD..origin/"${BRANCH}" 2>/dev/null || echo "0")"
fi

# Build changelog (last 30 commits we're behind)
CHANGELOG="[]"
if [[ "$COMMITS_BEHIND" -gt 0 ]]; then
  CHANGELOG="$(git log --oneline --format='{"hash":"%h","message":"%s","date":"%aI","author":"%an"}' HEAD..origin/"${BRANCH}" 2>/dev/null | head -30 | while IFS= read -r line; do
    # Escape any double quotes in the message that aren't already escaped
    echo "$line"
  done | paste -sd ',' | sed 's/^/[/' | sed 's/$/]/')"
  # Fallback if jq-less approach fails
  if [[ -z "$CHANGELOG" ]] || [[ "$CHANGELOG" == "[]" ]]; then
    CHANGELOG="[]"
  fi
fi

# Write status
cat > "$STATUS_FILE" <<EOF
{
  "branch": "${BRANCH}",
  "currentCommit": "${CURRENT_SHORT}",
  "currentCommitFull": "${CURRENT_COMMIT}",
  "currentMessage": "${CURRENT_MSG}",
  "currentDate": "${CURRENT_DATE}",
  "remoteCommit": "${REMOTE_SHORT}",
  "remoteCommitFull": "${REMOTE_COMMIT}",
  "commitsBehind": ${COMMITS_BEHIND},
  "changelog": ${CHANGELOG},
  "checkedAt": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "error": null
}
EOF

echo "Update check complete: ${COMMITS_BEHIND} commit(s) behind on ${BRANCH}"
