#!/bin/bash
# =============================================================================
# Server Monitorizare v2 - Migration Restore Script
# =============================================================================
# Restores a backup archive produced by backup_system.sh onto a new server.
#
# Usage:
#   ./scripts/restore_backup.sh <backup.tar.gz> [--db-only] [--ansible-only]
#
# What it does:
#   1. Extracts the archive to a temp staging area
#   2. Restores the SQLite database (with a safety backup of any existing DB)
#   3. Restores Ansible inventory, playbooks, ssh_keys, ansible.cfg
#   4. Restores WMT releases and ansible_settings.json
#   5. Fixes SSH key permissions (must be 600 for Ansible)
#   6. Prints post-restore checklist
#
# For a fresh server install, run this AFTER:
#   pip install -r requirements.txt
# =============================================================================

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
APP_DIR="$(dirname "$SCRIPT_DIR")"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")

# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
log()  { echo "[$(date '+%H:%M:%S')] $*"; }
ok()   { echo "  [OK] $*"; }
warn() { echo "  [WARN] $*"; }
err()  { echo "  [ERROR] $*" >&2; }

usage() {
    echo "Usage: $0 <path/to/backup.tar.gz> [--db-only | --ansible-only]"
    echo ""
    echo "Options:"
    echo "  --db-only       Restore only the SQLite database"
    echo "  --ansible-only  Restore only Ansible files (inventory, playbooks, ssh_keys)"
    echo ""
    echo "Example:"
    echo "  $0 data/backups/smv2_backup_20260708_020000.tar.gz"
    exit 1
}

# ---------------------------------------------------------------------------
# Parse args
# ---------------------------------------------------------------------------
ARCHIVE="${1:-}"
MODE="all"   # all | db-only | ansible-only
YES=0        # set to 1 by --yes to skip interactive confirmation

[[ -n "$ARCHIVE" ]] || usage
[[ -f "$ARCHIVE" ]] || { err "Archive not found: $ARCHIVE"; exit 1; }

for arg in "${@:2}"; do
    case "$arg" in
        --db-only)      MODE="db-only" ;;
        --ansible-only) MODE="ansible-only" ;;
        --yes|-y)       YES=1 ;;
        *) err "Unknown option: $arg"; usage ;;
    esac
done

# ---------------------------------------------------------------------------
# Extract archive
# ---------------------------------------------------------------------------
log "Extracting archive: $ARCHIVE"
STAGE_DIR=$(mktemp -d)
trap 'rm -rf "$STAGE_DIR"' EXIT

tar -xzf "$ARCHIVE" -C "$STAGE_DIR"
log "Extracted to staging: $STAGE_DIR"

# Show manifest if present
if [[ -f "$STAGE_DIR/BACKUP_MANIFEST.txt" ]]; then
    echo ""
    echo "=== Backup Manifest ==="
    cat "$STAGE_DIR/BACKUP_MANIFEST.txt"
    echo "========================"
    echo ""
fi

# ---------------------------------------------------------------------------
# Confirm before proceeding
# ---------------------------------------------------------------------------
if [[ "$YES" == "1" ]]; then
    log "Non-interactive mode (--yes) — proceeding automatically."
else
    read -r -p "Proceed with restore to $APP_DIR ? [y/N] " confirm
    [[ "${confirm,,}" == "y" ]] || { log "Aborted."; exit 0; }
fi

# ---------------------------------------------------------------------------
# Restore: SQLite database
# ---------------------------------------------------------------------------
restore_db() {
    local src="$STAGE_DIR/enhanced_monitoring.db"
    local dst="$APP_DIR/data/enhanced_monitoring.db"

    if [[ ! -f "$src" ]]; then
        warn "No database file in archive — skipping DB restore"
        return
    fi

    mkdir -p "$APP_DIR/data"

    # Safety backup of any existing database
    if [[ -f "$dst" ]]; then
        local safety_bak="${dst}.pre_restore_${TIMESTAMP}.bak"
        cp "$dst" "$safety_bak"
        ok "Existing DB saved as safety backup: $(basename "$safety_bak")"
    fi

    cp "$src" "$dst"
    ok "Database restored: $dst ($(du -sh "$dst" | cut -f1))"

    # Quick sanity check
    local dev_count; dev_count=$(sqlite3 "$dst" "SELECT COUNT(*) FROM devices;" 2>/dev/null || echo "?")
    ok "Devices in restored DB: $dev_count"
}

# ---------------------------------------------------------------------------
# Restore: Ansible files
# ---------------------------------------------------------------------------
restore_ansible() {
    local src="$STAGE_DIR/ansible"

    if [[ ! -d "$src" ]]; then
        warn "No ansible/ directory in archive — skipping"
        return
    fi

    # Backup existing ansible dir if present
    if [[ -d "$APP_DIR/ansible" ]]; then
        local bak="$APP_DIR/ansible.pre_restore_${TIMESTAMP}.bak"
        mv "$APP_DIR/ansible" "$bak"
        ok "Existing ansible/ moved to: $(basename "$bak")"
    fi

    cp -a "$src" "$APP_DIR/ansible"

    # Critical: SSH private key must be 600 or Ansible rejects it
    if [[ -f "$APP_DIR/ansible/ssh_keys/app_key" ]]; then
        chmod 600 "$APP_DIR/ansible/ssh_keys/app_key"
        ok "SSH private key permissions set to 600"
    fi

    ok "Ansible directory restored"
    ok "Playbooks: $(ls "$APP_DIR/ansible/playbooks/"*.yml 2>/dev/null | wc -l) files"
    ok "Inventory hosts: $(grep -c 'ansible_host:' "$APP_DIR/ansible/inventory/dynamic_inventory.yaml" 2>/dev/null || echo 0)"
}

# ---------------------------------------------------------------------------
# Restore: WMT releases
# ---------------------------------------------------------------------------
restore_wmt_releases() {
    local src="$STAGE_DIR/wmt_releases"
    if [[ ! -d "$src" ]]; then return; fi

    mkdir -p "$APP_DIR/data/wmt_releases"
    # Only copy files not already present (don't overwrite newer releases)
    for f in "$src"/*; do
        local fname; fname=$(basename "$f")
        if [[ ! -f "$APP_DIR/data/wmt_releases/$fname" ]]; then
            cp "$f" "$APP_DIR/data/wmt_releases/"
            ok "WMT release restored: $fname"
        else
            ok "WMT release already present (skipped): $fname"
        fi
    done
}

# ---------------------------------------------------------------------------
# Restore: ansible_settings.json
# ---------------------------------------------------------------------------
restore_settings() {
    local src="$STAGE_DIR/ansible_settings.json"
    if [[ ! -f "$src" ]]; then return; fi

    local dst="$APP_DIR/data/ansible_settings.json"
    if [[ -f "$dst" ]]; then
        cp "$dst" "${dst}.pre_restore_${TIMESTAMP}.bak"
    fi
    cp "$src" "$dst"
    ok "ansible_settings.json restored"
}

# ---------------------------------------------------------------------------
# Restore: config/
# ---------------------------------------------------------------------------
restore_config() {
    local src="$STAGE_DIR/config"
    if [[ ! -d "$src" ]]; then return; fi

    if [[ -d "$APP_DIR/config" ]]; then
        ok "config/ already present — skipping (manual merge may be needed)"
        warn "Backup config is in: $STAGE_DIR/config/ (not auto-applied)"
        return
    fi
    cp -a "$src" "$APP_DIR/config"
    ok "config/ restored"
}

# ---------------------------------------------------------------------------
# Dispatch
# ---------------------------------------------------------------------------
log "Restore mode: $MODE"

case "$MODE" in
    all)
        restore_db
        restore_ansible
        restore_wmt_releases
        restore_settings
        restore_config
        ;;
    db-only)
        restore_db
        ;;
    ansible-only)
        restore_ansible
        restore_settings
        ;;
esac

# ---------------------------------------------------------------------------
# Post-restore checklist
# ---------------------------------------------------------------------------
echo ""
echo "================================================================"
echo " Post-Restore Checklist"
echo "================================================================"
echo " 1. Install Python dependencies (if fresh server):"
echo "      cd $APP_DIR && pip install -r requirements.txt"
echo ""
echo " 2. Start the application:"
echo "      cd $APP_DIR && python main.py"
echo ""
echo " 3. Verify device list loads at:  http://<new-server-ip>:5000"
echo ""
echo " 4. Test Ansible connectivity:"
echo "      cd $APP_DIR/ansible && ansible -i inventory/dynamic_inventory.yaml all -m ping --limit 1"
echo ""
echo " 5. If the new server IP has changed, update any WMT devices"
echo "    pointing to the old server URL (wmt_global_config.server_log_url)"
echo "    via the admin UI or:"
echo "      sqlite3 data/enhanced_monitoring.db \\"
echo "        \"UPDATE wmt_global_config SET server_log_url='http://<NEW_IP>:5000/api/log';\""
echo ""
echo " 6. Re-install cron backup on the new server:"
echo "      bash $SCRIPT_DIR/backup_system.sh install-cron"
echo ""
echo "================================================================"
log "Restore completed."
