#!/usr/bin/env bash
# onx-db-version-prepare — Pre-flight check + backup before MySQL/MariaDB upgrade.
#
# WHM "MySQL Upgrade" muadili — version-switch'in zorunlu ön adımı.
# Bu adım veri kaybını önler: tam mysqldump backup + compat scan.
#
# Input (stdin JSON):
#   target_version   string   "8.0" (MySQL) | "10.11" | "11.4" (MariaDB)
#   target_engine    string?  "mysql" | "mariadb" — default current engine
#
# Output (stdout JSON):
#   {
#     "current_version": "MariaDB 10.11.6",
#     "current_engine": "mariadb",
#     "target_version": "11.4",
#     "target_engine": "mariadb",
#     "backup_path": "/var/backups/onox/pre-upgrade-1700000000.sql.gz",
#     "backup_size_mb": 320,
#     "backup_sha256": "...",
#     "connections_active": 5,
#     "deprecated_features": ["VARCHAR latin1 swedish_ci on `db1`.`old_table`"],
#     "estimated_downtime_min": 8,
#     "go_no_go": "go"
#   }
#
# Exit codes: 0=ok 1=invalid-input 2=preflight-fail 3=backup-fail
#
# Deployed to: /usr/local/onoxsoft/bin/onx-db-version-prepare

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" "")

[[ -z "${TARGET_VERSION}" ]] && onx_die 1 "target_version is required"
[[ "${TARGET_VERSION}" =~ ^[0-9]+\.[0-9]+(\.[0-9]+)?$ ]] || onx_die 1 "invalid target_version format"

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

# ── Detect current engine + version ──────────────────────────────────────────
CURRENT_ENGINE="unknown"
CURRENT_VERSION="unknown"

if command -v mysql >/dev/null 2>&1; then
    VER_LINE=$(mysql --version 2>/dev/null || echo "")
    if [[ "${VER_LINE}" =~ MariaDB ]]; then
        CURRENT_ENGINE="mariadb"
    elif [[ "${VER_LINE}" =~ MySQL|Distrib ]]; then
        CURRENT_ENGINE="mysql"
    fi
    CURRENT_VERSION=$(echo "${VER_LINE}" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || echo "unknown")
fi

[[ -z "${TARGET_ENGINE}" ]] && TARGET_ENGINE="${CURRENT_ENGINE}"

# ── Active connections ───────────────────────────────────────────────────────
CONNS_ACTIVE=0
if mysqladmin ping >/dev/null 2>&1; then
    CONNS_ACTIVE=$(mysqladmin processlist 2>/dev/null | grep -cE '^\| *[0-9]+' || true)
fi

# ── Backup ───────────────────────────────────────────────────────────────────
BACKUP_DIR="/var/backups/onox"
mkdir -p "${BACKUP_DIR}"
TS=$(date -u +"%s")
BACKUP_PATH="${BACKUP_DIR}/pre-upgrade-${TS}.sql.gz"

onx_log "Backing up all databases to ${BACKUP_PATH}"
if ! mysqldump --all-databases --routines --triggers --events --single-transaction 2>/dev/null \
        | gzip > "${BACKUP_PATH}"; then
    onx_die 3 "mysqldump failed — check credentials in /root/.my.cnf"
fi

BACKUP_BYTES=$(stat -c%s "${BACKUP_PATH}" 2>/dev/null || echo "0")
BACKUP_MB=$(( BACKUP_BYTES / 1024 / 1024 ))
BACKUP_SHA=$(sha256sum "${BACKUP_PATH}" 2>/dev/null | awk '{print $1}' || echo "")

# ── Deprecated feature scan (basic) ──────────────────────────────────────────
DEPRECATED=()
if mysql -e "SHOW DATABASES" >/dev/null 2>&1; then
    # latin1 swedish_ci scan (5.7 → 8.0 issue)
    while IFS= read -r row; do
        [[ -n "${row}" ]] && DEPRECATED+=("${row}")
    done < <(mysql -Nse "
        SELECT CONCAT(TABLE_SCHEMA, '.', TABLE_NAME, ' uses latin1')
        FROM information_schema.TABLES
        WHERE TABLE_COLLATION LIKE 'latin1%'
        AND TABLE_SCHEMA NOT IN ('information_schema','mysql','performance_schema','sys')
        LIMIT 10
    " 2>/dev/null || true)
fi

DEPRECATED_JSON=$(printf '%s\n' "${DEPRECATED[@]}" | jq -Rsn '[inputs | select(length > 0)]')

# ── Estimated downtime: backup size + version skip distance ──────────────────
# Heuristik: ~1dk/100MB backup + 3dk/version-jump
EST_DOWNTIME=$(( (BACKUP_MB / 100) + 3 ))
[[ ${EST_DOWNTIME} -lt 5 ]] && EST_DOWNTIME=5
[[ ${EST_DOWNTIME} -gt 60 ]] && EST_DOWNTIME=60

GO_NO_GO="go"
[[ ${#DEPRECATED[@]} -gt 5 ]] && GO_NO_GO="warn"
[[ ${CONNS_ACTIVE} -gt 50 ]] && GO_NO_GO="warn"

jq -n \
    --arg current_version "${CURRENT_VERSION}" \
    --arg current_engine "${CURRENT_ENGINE}" \
    --arg target_version "${TARGET_VERSION}" \
    --arg target_engine "${TARGET_ENGINE}" \
    --arg backup_path "${BACKUP_PATH}" \
    --argjson backup_size_mb "${BACKUP_MB}" \
    --arg backup_sha256 "${BACKUP_SHA}" \
    --argjson connections_active "${CONNS_ACTIVE}" \
    --argjson deprecated_features "${DEPRECATED_JSON}" \
    --argjson estimated_downtime_min "${EST_DOWNTIME}" \
    --arg go_no_go "${GO_NO_GO}" \
    '{current_version: $current_version, current_engine: $current_engine,
      target_version: $target_version, target_engine: $target_engine,
      backup_path: $backup_path, backup_size_mb: $backup_size_mb,
      backup_sha256: $backup_sha256, connections_active: $connections_active,
      deprecated_features: $deprecated_features,
      estimated_downtime_min: $estimated_downtime_min, go_no_go: $go_no_go}'

onx_log "DB upgrade preflight: ${CURRENT_ENGINE} ${CURRENT_VERSION} → ${TARGET_ENGINE} ${TARGET_VERSION} (backup=${BACKUP_MB}MB, go=${GO_NO_GO})"
