#!/bin/bash
# =============================================================================
# update_mars_url.sh
# Replaces mars.42gears.com with mars.astrouploads.com in appsettings.json,
# recreates the Kubernetes secret, and restarts SureMDM deployments.
# =============================================================================

set -euo pipefail

# ---------------------------------------------------------------------------
# JSON validation helper — uses python3/python (no jq required)
# Works fully offline on any standard Linux system.
# ---------------------------------------------------------------------------
validate_json() {
    local file="$1"
    if command -v python3 &>/dev/null; then
        python3 -c "import sys, json; json.load(open('${file}'))" 2>/dev/null
    elif command -v python &>/dev/null; then
        python -c "import sys, json; json.load(open('${file}'))" 2>/dev/null
    else
        # No python available — skip validation, warn and continue
        warn "python/python3 not found — skipping JSON validation."
        return 0
    fi
}

# ---------------------------------------------------------------------------
# Configuration
# ---------------------------------------------------------------------------
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
APPSETTINGS_FILE="${SCRIPT_DIR}/appsettings/suremdm/appsettings.json"
NAMESPACE="suremdm"
SECRET_NAME="suremdm-secret"
LOG_DIR="${SCRIPT_DIR}/logfiles"
LOG_FILE="${LOG_DIR}/update_mars_url_$(date '+%Y%m%d_%H%M%S').log"
OLD_HOST="mars.42gears.com"
NEW_HOST="mars.astrouploads.com"
POD_READY_TIMEOUT=300   # seconds (5 minutes)
POD_CHECK_INTERVAL=10   # seconds between readiness polls

# ---------------------------------------------------------------------------
# Logging helpers
# ---------------------------------------------------------------------------
mkdir -p "${LOG_DIR}"

# All stdout/stderr ? log file; console gets only what we explicitly echo via ui_* functions
exec 3>&1                        # fd 3 = real console
exec >> "${LOG_FILE}" 2>&1       # fd 1 & 2 ? log file only

_ts()    { date '+%Y-%m-%d %H:%M:%S'; }
log()    { echo "[$(_ts)] [INFO]  $*"; }
warn()   { echo "[$(_ts)] [WARN]  $*"; }
error()  { echo "[$(_ts)] [ERROR] $*"; }

# Section heading — console only (ASCII-safe, no UTF-8 box chars)
section() {
    echo ""                                    >&3
    echo "  $*"                                >&3
    echo "  ------------------------------------------------" >&3
    echo ""
    echo "=== $* ==="
}

# User-facing one-liners — console only, no technical detail (ASCII-safe)
ui_ok()   { echo "  [OK]  $*" >&3; log "OK:   $*"; }
ui_info() { echo "  [..] $*"  >&3; log "INFO: $*"; }
ui_wait() { printf "  [..] $*\r" >&3; }
ui_fail() { echo "  [!!] $*"  >&3; log "FAIL: $*"; }

# ---------------------------------------------------------------------------
# Startup
# ---------------------------------------------------------------------------
log "Script     : ${BASH_SOURCE[0]}"
log "Log file   : ${LOG_FILE}"
log "Working dir: ${SCRIPT_DIR}"

# Print product header to console (ASCII-safe)
{
    echo ""
    echo "  +-------------------------------------------------+"
    echo "  |           SureMDM -- System Update              |"
    echo "  +-------------------------------------------------+"
    echo ""
} >&3

# Silent prerequisite checks
for cmd in kubectl sed; do
    if ! command -v "$cmd" &>/dev/null; then
        error "Required tool not found: $cmd"
        ui_fail "A required system component is missing. Please contact support."
        exit 1
    fi
    log "Found: $cmd ($(command -v "$cmd"))"
done

if [[ ! -f "${APPSETTINGS_FILE}" ]]; then
    error "appsettings.json not found at: ${APPSETTINGS_FILE}"
    ui_fail "Update prerequisites not met. Please contact support."
    exit 1
fi

if ! kubectl get namespace "${NAMESPACE}" &>/dev/null; then
    error "Kubernetes namespace '${NAMESPACE}' does not exist."
    ui_fail "The application environment is not available. Please contact support."
    exit 1
fi

# ---------------------------------------------------------------------------
# Section 1 — Updating Configuration File
# ---------------------------------------------------------------------------
section "Updating Configuration File"

OCCURRENCES=$(grep -o "${OLD_HOST}" "${APPSETTINGS_FILE}" | wc -l | tr -d '[:space:]')
OCCURRENCES="${OCCURRENCES:-0}"
log "Occurrences of '${OLD_HOST}' found: ${OCCURRENCES}"

if [[ "${OCCURRENCES}" -eq 0 ]]; then
    warn "No occurrences of '${OLD_HOST}' found. Already up to date."
    ui_ok "Configuration is already up to date. No changes required."
else
    BACKUP_FILE="${APPSETTINGS_FILE}.bak.$(date '+%Y%m%d_%H%M%S')"
    cp "${APPSETTINGS_FILE}" "${BACKUP_FILE}"
    log "Backup created: ${BACKUP_FILE}"

    TMP_FILE=$(mktemp)
    sed "s|${OLD_HOST}|${NEW_HOST}|g" "${APPSETTINGS_FILE}" > "${TMP_FILE}"
    mv "${TMP_FILE}" "${APPSETTINGS_FILE}"

    REPLACED=$(grep -o "${NEW_HOST}" "${APPSETTINGS_FILE}" | wc -l | tr -d '[:space:]')
    log "Replacement complete. New occurrences of '${NEW_HOST}': ${REPLACED}"

    if ! validate_json "${APPSETTINGS_FILE}"; then
        error "appsettings.json is not valid JSON after replacement. Restoring backup."
        cp "${BACKUP_FILE}" "${APPSETTINGS_FILE}"
        ui_fail "Configuration update failed. The previous configuration has been restored."
        exit 1
    fi

    ui_ok "Configuration updated successfully."
fi

# ---------------------------------------------------------------------------
# Section 2 — Applying Configuration (secret recreate — silent)
# ---------------------------------------------------------------------------
log "=== Applying Configuration ==="

if kubectl get secret "${SECRET_NAME}" -n "${NAMESPACE}" &>/dev/null; then
    log "Deleting existing secret '${SECRET_NAME}'..."
    kubectl delete secret "${SECRET_NAME}" -n "${NAMESPACE}"
    log "Secret deleted."
else
    log "Secret '${SECRET_NAME}' did not exist — creating fresh."
fi

kubectl create secret generic "${SECRET_NAME}" \
    --from-file="${APPSETTINGS_FILE}" \
    -n "${NAMESPACE}"
log "Secret '${SECRET_NAME}' created."

# ---------------------------------------------------------------------------
# Section 3 — Restarting Application Services
# ---------------------------------------------------------------------------
section "Restarting Application Services"
ui_info "Applying changes across all services. This may take a few minutes."

kubectl rollout restart deployment -n "${NAMESPACE}" || true
log "Rolling restart initiated for all deployments in '${NAMESPACE}'."

# Wait for all pods
ELAPSED=0
ALL_READY=false

while [[ ${ELAPSED} -lt ${POD_READY_TIMEOUT} ]]; do
    TOTAL=$(kubectl get pods -n "${NAMESPACE}" --no-headers 2>/dev/null | wc -l | tr -d '[:space:]' || echo "0")
    TOTAL="${TOTAL:-0}"

    NOT_READY=$(kubectl get pods -n "${NAMESPACE}" --no-headers 2>/dev/null \
        | awk '{print $2, $3}' \
        | grep -v -E '^[0-9]+/[0-9]+ (Running|Completed|Succeeded)$' \
        | wc -l | tr -d '[:space:]' || echo "0")
    NOT_READY="${NOT_READY:-0}"

    log "Pod status: Total=${TOTAL}, NotReady=${NOT_READY}, Elapsed=${ELAPSED}s"

    if [[ "${NOT_READY}" -eq 0 && "${TOTAL}" -gt 0 ]]; then
        ALL_READY=true
        break
    fi

    sleep "${POD_CHECK_INTERVAL}"
    ELAPSED=$((ELAPSED + POD_CHECK_INTERVAL))
    REMAINING=$((POD_READY_TIMEOUT - ELAPSED))
    ui_wait "Services restarting, please wait... (${REMAINING}s remaining)"
done

if [[ "${ALL_READY}" == true ]]; then
    log "All pods ready after ${ELAPSED}s."
else
    warn "Timeout after ${POD_READY_TIMEOUT}s. Some services may still be initialising."
    kubectl get pods -n "${NAMESPACE}" --no-headers >> "${LOG_FILE}" 2>&1 || true
fi

# Restart shield last (silent on console)
log "=== Restarting Shield Service ==="
if kubectl get deployment shield-deployment -n "${NAMESPACE}" &>/dev/null; then
    kubectl rollout restart deployment shield-deployment -n "${NAMESPACE}" || true
    log "Shield restart triggered."
    if kubectl rollout status deployment/shield-deployment -n "${NAMESPACE}" --timeout=120s; then
        log "Shield rollout complete."
    else
        warn "Shield rollout did not complete within 120s."
    fi
else
    warn "shield-deployment not found — skipped."
fi

ui_ok "All services have been restarted successfully."

# ---------------------------------------------------------------------------
# Summary
# ---------------------------------------------------------------------------
{
    echo ""
    echo "  +-------------------------------------------------+"
    echo "  |               Update Complete                   |"
    echo "  +-------------------------------------------------+"
    echo ""
    echo "  The system has been updated and all services are"
    echo "  running with the latest configuration."
    echo ""
} >&3

log "Script completed successfully."
