#!/usr/bin/env bash
# Yıkıcı olmayan restore provası: son backup'ı izole hedef DB'ye geri yükler,
# temel tablo/count doğrulaması yapar ve JSON raporu yazar.
set -euo pipefail

usage() {
  cat <<'EOF'
Kullanim:
  ./scripts/rehearse-restore.sh [--keep-db] [backup.sql.gz]

Notlar:
  - Varsayilan backup: .local/backups/mysql altindaki en yeni .sql.gz
  - Varsayilan hedef DB: <DB_NAME>_restore_rehearsal_<UTC_TIMESTAMP>
  - Rapor: .local/restore-rehearsals/*.json
EOF
}

KEEP_DB=0
BACKUP_FILE=""
for arg in "$@"; do
  case "$arg" in
    --keep-db)
      KEEP_DB=1
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      if [[ -n "$BACKUP_FILE" ]]; then
        echo "Beklenmeyen arguman: $arg" >&2
        usage >&2
        exit 1
      fi
      BACKUP_FILE="$arg"
      ;;
  esac
done

_SCRIPT_SOURCE="${BASH_SOURCE[0]:-$0}"
if [[ "$_SCRIPT_SOURCE" != /* ]]; then
  _SCRIPT_SOURCE="$PWD/${_SCRIPT_SOURCE#./}"
fi
ROOT="$(cd "$(dirname "$_SCRIPT_SOURCE")/.." && pwd)"
ENV_FILE="${FAUNAMIX_ENV_FILE:-$ROOT/api/.env}"
REPORT_DIR="${FAUNAMIX_RESTORE_REHEARSAL_REPORT_DIR:-$ROOT/.local/restore-rehearsals}"
BACKUP_DIR="${FAUNAMIX_DB_BACKUP_DIR:-$ROOT/.local/backups/mysql}"
TIMESTAMP="$(date -u +%Y%m%dT%H%M%SZ)"
TEMP_ENV=""
MYSQL_BIN=""
SOURCE_DB=""
TARGET_DB=""
CREATED_TARGET_DB=0

load_env() {
  if [[ -f "$ENV_FILE" ]]; then
    set -a
    # shellcheck disable=SC1090
    source "$ENV_FILE"
    set +a
  fi
}

apply_aliases() {
  DB_HOST="${DB_HOST:-${MYSQL_HOST:-127.0.0.1}}"
  DB_PORT="${DB_PORT:-${MYSQL_PORT:-3306}}"
  DB_NAME="${DB_NAME:-${MYSQL_DATABASE:-faunamix}}"
  DB_USER="${DB_USER:-${MYSQL_USER:-root}}"
  if [[ -z "${DB_PASS:-}" ]]; then
    DB_PASS="${MYSQL_PASSWORD:-${MYSQL_ROOT_PASSWORD:-}}"
  fi
}

pick_mysql_bin() {
  if command -v mysql >/dev/null 2>&1; then
    echo "mysql"
    return
  fi
  if command -v mariadb >/dev/null 2>&1; then
    echo "mariadb"
    return
  fi
  echo "Eksik: mysql veya mariadb istemcisi bulunamadi." >&2
  exit 1
}

resolve_latest_backup() {
  local latest
  latest="$(ls -1t "$BACKUP_DIR"/*.sql.gz 2>/dev/null | head -1 || true)"
  if [[ -z "$latest" ]]; then
    latest="$(ls -1t "$BACKUP_DIR"/*.sql 2>/dev/null | head -1 || true)"
  fi
  if [[ -z "$latest" ]]; then
    echo "Restore provasi icin backup bulunamadi: $BACKUP_DIR" >&2
    exit 1
  fi
  echo "$latest"
}

mysql_args() {
  local args=( --host="$DB_HOST" --port="$DB_PORT" --protocol=TCP --user="$DB_USER" --default-character-set=utf8mb4 --batch --skip-column-names )
  if [[ "$DB_HOST" == *".railway.internal"* ]] && [[ "${FAUNAMIX_MYSQL_SSL:-}" != "1" ]]; then
    args+=( --skip-ssl )
  elif [[ "$DB_HOST" == *".rlwy.net"* ]] || [[ "${FAUNAMIX_MYSQL_SSL:-}" == "1" ]]; then
    args+=( --ssl )
  fi
  printf '%s\0' "${args[@]}"
}

mysql_exec_raw() {
  local query="$1"
  local db="${2:-}"
  local -a args=()
  while IFS= read -r -d '' item; do
    args+=("$item")
  done < <(mysql_args)
  if [[ -n "$db" ]]; then
    if [[ -n "${DB_PASS:-}" ]]; then
      MYSQL_PWD="$DB_PASS" "$MYSQL_BIN" "${args[@]}" "$db" -e "$query"
    else
      "$MYSQL_BIN" "${args[@]}" "$db" -e "$query"
    fi
  else
    if [[ -n "${DB_PASS:-}" ]]; then
      MYSQL_PWD="$DB_PASS" "$MYSQL_BIN" "${args[@]}" -e "$query"
    else
      "$MYSQL_BIN" "${args[@]}" -e "$query"
    fi
  fi
}

json_escape() {
  local raw="$1"
  raw="${raw//\\/\\\\}"
  raw="${raw//\"/\\\"}"
  raw="${raw//$'\n'/\\n}"
  raw="${raw//$'\r'/\\r}"
  raw="${raw//$'\t'/\\t}"
  printf '%s' "$raw"
}

write_env_line() {
  local key="$1"
  local value="${2:-}"
  printf '%s=%q\n' "$key" "$value" >> "$TEMP_ENV"
}

cleanup() {
  if [[ -n "$TEMP_ENV" && -f "$TEMP_ENV" ]]; then
    rm -f "$TEMP_ENV"
  fi
  if [[ "$KEEP_DB" != "1" && "$CREATED_TARGET_DB" == "1" && -n "$TARGET_DB" && -n "$MYSQL_BIN" ]]; then
    mysql_exec_raw "DROP DATABASE IF EXISTS \`$TARGET_DB\`;" >/dev/null 2>&1 || true
  fi
}
trap cleanup EXIT

load_env
apply_aliases

: "${DB_HOST:?DB_HOST veya MYSQL_HOST gerekli}"
: "${DB_PORT:?DB_PORT veya MYSQL_PORT gerekli}"
: "${DB_NAME:?DB_NAME veya MYSQL_DATABASE gerekli}"
: "${DB_USER:?DB_USER veya MYSQL_USER gerekli}"

MYSQL_BIN="$(pick_mysql_bin)"
SOURCE_DB="$DB_NAME"
if [[ -z "$BACKUP_FILE" ]]; then
  BACKUP_FILE="$(resolve_latest_backup)"
fi
if [[ ! -f "$BACKUP_FILE" ]]; then
  echo "Backup dosyasi bulunamadi: $BACKUP_FILE" >&2
  exit 1
fi

TARGET_DB="${FAUNAMIX_RESTORE_REHEARSAL_DB:-${SOURCE_DB}_restore_rehearsal_${TIMESTAMP//[-:TZ]/}}"
if [[ "$TARGET_DB" == "$SOURCE_DB" ]]; then
  echo "Restore rehearsal hedefi source DB ile ayni olamaz: $TARGET_DB" >&2
  exit 1
fi
if [[ ! "$TARGET_DB" =~ ^[A-Za-z0-9_]+$ ]]; then
  echo "Gecersiz target DB adi: $TARGET_DB" >&2
  exit 1
fi
if [[ "$TARGET_DB" != *restore* && "$TARGET_DB" != *rehearsal* ]]; then
  echo "Guvenlik icin target DB adi 'restore' veya 'rehearsal' icermeli: $TARGET_DB" >&2
  exit 1
fi

EXISTS_COUNT="$(mysql_exec_raw "SELECT COUNT(*) FROM information_schema.schemata WHERE schema_name = '$TARGET_DB';")"
if [[ "$EXISTS_COUNT" != "0" ]]; then
  if [[ "${FAUNAMIX_RESTORE_REHEARSAL_DROP_EXISTING:-}" == "1" ]]; then
    mysql_exec_raw "DROP DATABASE IF EXISTS \`$TARGET_DB\`;"
  else
    echo "Target DB zaten var: $TARGET_DB (silmek icin FAUNAMIX_RESTORE_REHEARSAL_DROP_EXISTING=1)" >&2
    exit 1
  fi
fi

mysql_exec_raw "CREATE DATABASE \`$TARGET_DB\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
CREATED_TARGET_DB=1

TEMP_ENV="$(mktemp "${TMPDIR:-/tmp}/faunamix-restore-env.XXXXXX")"
chmod 600 "$TEMP_ENV"
: > "$TEMP_ENV"
write_env_line "DB_HOST" "$DB_HOST"
write_env_line "DB_PORT" "$DB_PORT"
write_env_line "DB_NAME" "$TARGET_DB"
write_env_line "DB_USER" "$DB_USER"
write_env_line "DB_PASS" "${DB_PASS:-}"
write_env_line "FAUNAMIX_MYSQL_SSL" "${FAUNAMIX_MYSQL_SSL:-}"

FAUNAMIX_ENV_FILE="$TEMP_ENV" \
FAUNAMIX_RESTORE_CONFIRM="RESTORE_$TARGET_DB" \
"$ROOT/scripts/restore-database.sh" --skip-pre-backup "$BACKUP_FILE" >/dev/null

SOURCE_TABLE_COUNT="$(mysql_exec_raw "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '$SOURCE_DB';")"
TARGET_TABLE_COUNT="$(mysql_exec_raw "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '$TARGET_DB';")"
if [[ "$SOURCE_TABLE_COUNT" != "$TARGET_TABLE_COUNT" ]]; then
  echo "Tablo sayisi uyusmuyor: source=$SOURCE_TABLE_COUNT target=$TARGET_TABLE_COUNT" >&2
  exit 1
fi

TABLES_TO_VERIFY=( admin_users products nav_menu footer_menu routes ecommerce_orders )
VERIFIED_COUNT=0
TABLE_JSON=""
for table in "${TABLES_TO_VERIFY[@]}"; do
  SRC_EXISTS="$(mysql_exec_raw "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '$SOURCE_DB' AND table_name = '$table';")"
  if [[ "$SRC_EXISTS" != "1" ]]; then
    continue
  fi
  TGT_EXISTS="$(mysql_exec_raw "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '$TARGET_DB' AND table_name = '$table';")"
  if [[ "$TGT_EXISTS" != "1" ]]; then
    echo "Target DB'de beklenen tablo yok: $table" >&2
    exit 1
  fi
  SRC_COUNT="$(mysql_exec_raw "SELECT COUNT(*) FROM \`$SOURCE_DB\`.\`$table\`;" "$SOURCE_DB")"
  TGT_COUNT="$(mysql_exec_raw "SELECT COUNT(*) FROM \`$TARGET_DB\`.\`$table\`;" "$TARGET_DB")"
  if [[ "$SRC_COUNT" != "$TGT_COUNT" ]]; then
    echo "Tablo sayisi uyusmuyor ($table): source=$SRC_COUNT target=$TGT_COUNT" >&2
    exit 1
  fi
  if [[ -n "$TABLE_JSON" ]]; then
    TABLE_JSON+=",\n"
  fi
  TABLE_JSON+="    {\"table\":\"$(json_escape "$table")\",\"source_count\":$SRC_COUNT,\"target_count\":$TGT_COUNT}"
  VERIFIED_COUNT=$((VERIFIED_COUNT + 1))
done

if (( VERIFIED_COUNT == 0 )); then
  echo "Restore provasi icin dogrulanacak tablo bulunamadi." >&2
  exit 1
fi

mkdir -p "$REPORT_DIR"
REPORT_FILE="$REPORT_DIR/restore-rehearsal-${TIMESTAMP}.json"
KEEP_DB_JSON="false"
if [[ "$KEEP_DB" == "1" ]]; then
  KEEP_DB_JSON="true"
fi

cat > "$REPORT_FILE" <<EOF
{
  "validated_at_utc": "$TIMESTAMP",
  "source_db": "$(json_escape "$SOURCE_DB")",
  "target_db": "$(json_escape "$TARGET_DB")",
  "backup_file": "$(json_escape "$BACKUP_FILE")",
  "kept_target_db": $KEEP_DB_JSON,
  "source_table_count": $SOURCE_TABLE_COUNT,
  "target_table_count": $TARGET_TABLE_COUNT,
  "verified_tables": [
$TABLE_JSON
  ]
}
EOF

echo "Restore rehearsal tamamlandi:"
echo "  source_db: $SOURCE_DB"
echo "  target_db: $TARGET_DB"
echo "  backup: $BACKUP_FILE"
echo "  report: $REPORT_FILE"
if [[ "$KEEP_DB" != "1" ]]; then
  echo "  cleanup: target DB script cikisinda silinecek"
fi
