#!/usr/bin/env bash
# onx-db-version-switch — Execute MySQL/MariaDB version upgrade.
#
# DRY-WET ayrımı: prepare zorunlu ön adım. Bu script gerçek migration'ı yapar.
# Service stop → repo swap → install → start → mysql_upgrade → verify.
#
# Input (stdin JSON):
#   target_version   string   "11.4" | "8.0"
#   target_engine    string   "mariadb" | "mysql"
#   backup_path      string   Prepare adımında üretilen backup
#   confirm_token    string   Sysapi'ya gönderilen sha (idempotent guard)
#
# Output (stdout JSON):
#   {
#     "upgraded": true,
#     "from": "MariaDB 10.11.6",
#     "to": "MariaDB 11.4.2",
#     "service_unit": "mariadb",
#     "mysql_upgrade_ok": true,
#     "downtime_seconds": 312
#   }
#
# Exit codes: 0=ok 1=invalid-input 2=preflight-fail 3=exec-fail 4=rolled-back
#
# Deployed to: /usr/local/onoxsoft/bin/onx-db-version-switch

set -euo pipefail

SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
# shellcheck source=_lib/common.sh
source "${SCRIPT_DIR}/_lib/common.sh"

INPUT=$(cat)
onx_require_json "${INPUT}"

TARGET_VERSION=$(onx_json_get "${INPUT}" "target_version")
TARGET_ENGINE=$(onx_json_get "${INPUT}" "target_engine")
BACKUP_PATH=$(onx_json_get "${INPUT}" "backup_path")
CONFIRM_TOKEN=$(onx_json_get "${INPUT}" "confirm_token")

[[ -z "${TARGET_VERSION}" || -z "${TARGET_ENGINE}" ]] && onx_die 1 "target_version and target_engine required"
[[ -z "${BACKUP_PATH}" ]] && onx_die 1 "backup_path is required (run onx-db-version-prepare first)"
[[ -z "${CONFIRM_TOKEN}" ]] && onx_die 1 "confirm_token is required (admin double-confirm)"
[[ -f "${BACKUP_PATH}" ]] || onx_die 2 "backup file not found: ${BACKUP_PATH}"

case "${TARGET_ENGINE}" in
    mysql|mariadb) ;;
    *) onx_die 1 "target_engine must be mysql or mariadb" ;;
esac

[[ $EUID -eq 0 ]] || onx_die 2 "must be run as root"

# ── Detect current ───────────────────────────────────────────────────────────
START_TS=$(date +%s)
FROM_VER=$(mysql --version 2>/dev/null | grep -oE '[A-Za-z]+ [0-9]+\.[0-9]+\.[0-9]+' | head -1 || echo "unknown")

SERVICE_UNIT="mariadb"
if [[ "${TARGET_ENGINE}" == "mysql" ]]; then
    SERVICE_UNIT="mysqld"
fi

onx_log "DB upgrade start: ${FROM_VER} → ${TARGET_ENGINE} ${TARGET_VERSION}"

# ── Stop service ─────────────────────────────────────────────────────────────
systemctl stop "${SERVICE_UNIT}" 2>/dev/null || systemctl stop mariadb 2>/dev/null \
    || systemctl stop mysqld 2>/dev/null || onx_die 3 "failed to stop DB service"

# ── Repo swap + install ──────────────────────────────────────────────────────
if command -v dnf >/dev/null 2>&1; then
    if [[ "${TARGET_ENGINE}" == "mariadb" ]]; then
        dnf module reset mariadb -y >/dev/null 2>&1 || true
        if ! dnf module install -y "mariadb:${TARGET_VERSION}" 2>/dev/null; then
            # Fallback: MariaDB upstream repo
            cat > /etc/yum.repos.d/mariadb-onox.repo <<EOF
[mariadb-onox]
name=MariaDB ${TARGET_VERSION}
baseurl=https://mirror.mariadb.org/yum/${TARGET_VERSION}/rhel9-amd64
gpgkey=https://supplychain.mariadb.com/MariaDB-Server-GPG-KEY
gpgcheck=1
enabled=1
EOF
            dnf install -y MariaDB-server MariaDB-client || onx_die 3 "MariaDB install failed"
        fi
    else
        dnf module reset mysql -y >/dev/null 2>&1 || true
        dnf module install -y "mysql:${TARGET_VERSION}" || onx_die 3 "MySQL install failed"
    fi
elif command -v apt >/dev/null 2>&1; then
    apt update >/dev/null 2>&1
    if [[ "${TARGET_ENGINE}" == "mariadb" ]]; then
        apt install -y "mariadb-server-${TARGET_VERSION}" || onx_die 3 "MariaDB install failed"
    else
        apt install -y "mysql-server-${TARGET_VERSION}" || onx_die 3 "MySQL install failed"
    fi
else
    onx_die 2 "no supported package manager (dnf/apt)"
fi

# ── Start service ────────────────────────────────────────────────────────────
systemctl enable --now "${SERVICE_UNIT}" 2>/dev/null \
    || systemctl enable --now mariadb 2>/dev/null \
    || systemctl enable --now mysqld 2>/dev/null \
    || onx_die 3 "failed to start ${SERVICE_UNIT} — check journalctl"

# Wait for socket
for i in {1..30}; do
    mysqladmin ping >/dev/null 2>&1 && break
    sleep 1
done
mysqladmin ping >/dev/null 2>&1 || onx_die 3 "DB did not come back online within 30s"

# ── mysql_upgrade ────────────────────────────────────────────────────────────
UPGRADE_OK="false"
if command -v mariadb-upgrade >/dev/null 2>&1; then
    mariadb-upgrade --force 2>/dev/null && UPGRADE_OK="true"
elif command -v mysql_upgrade >/dev/null 2>&1; then
    mysql_upgrade --force 2>/dev/null && UPGRADE_OK="true"
fi

# ── Verify ───────────────────────────────────────────────────────────────────
TO_VER=$(mysql --version 2>/dev/null | grep -oE '[A-Za-z]+ [0-9]+\.[0-9]+\.[0-9]+' | head -1 || echo "unknown")

END_TS=$(date +%s)
DOWNTIME=$(( END_TS - START_TS ))

jq -n \
    --argjson upgraded true \
    --arg from "${FROM_VER}" \
    --arg to "${TO_VER}" \
    --arg service_unit "${SERVICE_UNIT}" \
    --argjson mysql_upgrade_ok "${UPGRADE_OK}" \
    --argjson downtime_seconds "${DOWNTIME}" \
    --arg backup_path "${BACKUP_PATH}" \
    '{upgraded: $upgraded, from: $from, to: $to, service_unit: $service_unit,
      mysql_upgrade_ok: $mysql_upgrade_ok, downtime_seconds: $downtime_seconds,
      backup_path: $backup_path}'

onx_log "DB upgrade complete: ${FROM_VER} → ${TO_VER} (downtime=${DOWNTIME}s, upgrade_ok=${UPGRADE_OK})"
