#!/bin/bash
set -e

# Staging Database Refresh Script for MotoVaultPro
# Copies production database to staging (non-interactive)
# Usage: ./scripts/refresh-staging-db.sh [options]
#
# Prerequisites:
#   SSH key-based access from staging act_runner to production act_runner.
#
#   On STAGING (as act_runner):
#     ssh-keygen -t ed25519 -N "" -f ~/.ssh/id_ed25519
#     cat ~/.ssh/id_ed25519.pub  # Copy this output
#
#   On PRODUCTION (as root or sudo):
#     sudo -u act_runner mkdir -p ~/.ssh
#     sudo chmod 700 /home/act_runner/.ssh
#     sudo -u act_runner touch ~/.ssh/authorized_keys
#     sudo chmod 600 /home/act_runner/.ssh/authorized_keys
#     echo "PASTE_PUBLIC_KEY_HERE" | sudo tee -a /home/act_runner/.ssh/authorized_keys
#
#   Verify from STAGING:
#     ssh act_runner@172.30.1.36 echo "SSH OK"

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

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

# Server configuration
PRODUCTION_HOST="172.30.1.36"
PRODUCTION_USER="act_runner"
PRODUCTION_CONTAINER="mvp-postgres"

STAGING_CONTAINER="mvp-postgres-staging"
STAGING_BACKEND_CONTAINER="mvp-backend-staging"

# Database configuration
DATABASE_NAME="motovaultpro"
DATABASE_USER="postgres"

# Paths
BACKUP_DIR="/tmp/mvp-db-refresh"
STAGING_BACKUP="${BACKUP_DIR}/staging_backup_${TIMESTAMP}.sql.gz"
PRODUCTION_DUMP="${BACKUP_DIR}/production_dump_${TIMESTAMP}.sql"

# Options
DRY_RUN=false
SKIP_BACKUP=false
KEEP_DUMP=false

# Function to print colored output
print_info() {
    echo -e "${GREEN}[INFO]${NC} $1"
}

print_warn() {
    echo -e "${YELLOW}[WARN]${NC} $1"
}

print_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

print_step() {
    echo -e "${BLUE}[STEP]${NC} $1"
}

print_dry() {
    echo -e "${YELLOW}[DRY-RUN]${NC} Would: $1"
}

# Function to show usage
show_usage() {
    cat << EOF
Staging Database Refresh Script for MotoVaultPro

Copies the production database to staging. This script must be run on the
staging server and requires SSH access to the production server.

Usage: $0 [options]

Options:
    -h, --help          Show this help message
    --dry-run           Show what would happen without making changes
    --skip-backup       Skip staging backup (faster, less safe)
    --keep-dump         Keep the production dump file after import

Prerequisites:
    SSH key-based access from staging to production.

    # On STAGING (as act_runner):
    ssh-keygen -t ed25519 -N "" -f ~/.ssh/id_ed25519
    cat ~/.ssh/id_ed25519.pub  # Copy this output

    # On PRODUCTION (as root or sudo):
    sudo -u act_runner mkdir -p ~/.ssh
    sudo chmod 700 /home/act_runner/.ssh
    sudo -u act_runner touch ~/.ssh/authorized_keys
    sudo chmod 600 /home/act_runner/.ssh/authorized_keys
    echo "PASTE_KEY" | sudo tee -a /home/act_runner/.ssh/authorized_keys

    # Verify from STAGING:
    ssh ${PRODUCTION_USER}@${PRODUCTION_HOST} echo "SSH OK"

Examples:
    # Preview what would happen
    $0 --dry-run

    # Full refresh (recommended)
    $0

    # Quick refresh without staging backup
    $0 --skip-backup

EOF
    exit 0
}

# Parse command line arguments
while [[ $# -gt 0 ]]; do
    case $1 in
        -h|--help)
            show_usage
            ;;
        --dry-run)
            DRY_RUN=true
            shift
            ;;
        --skip-backup)
            SKIP_BACKUP=true
            shift
            ;;
        --keep-dump)
            KEEP_DUMP=true
            shift
            ;;
        *)
            print_error "Unknown option: $1"
            show_usage
            ;;
    esac
done

# Cleanup function
cleanup() {
    local exit_code=$?
    if [ "$KEEP_DUMP" = false ] && [ -f "$PRODUCTION_DUMP" ]; then
        rm -f "$PRODUCTION_DUMP"
    fi
    if [ $exit_code -ne 0 ]; then
        print_error "Script failed with exit code $exit_code"
        if [ -f "$STAGING_BACKUP" ]; then
            print_warn "Staging backup available at: $STAGING_BACKUP"
            print_warn "To restore: gunzip -c $STAGING_BACKUP | docker exec -i $STAGING_CONTAINER psql -U $DATABASE_USER -d $DATABASE_NAME"
        fi
    fi
    exit $exit_code
}
trap cleanup EXIT

# Header
echo ""
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE}  MotoVaultPro Staging Database Refresh${NC}"
echo -e "${BLUE}========================================${NC}"
echo ""

if [ "$DRY_RUN" = true ]; then
    print_warn "DRY RUN MODE - No changes will be made"
    echo ""
fi

# Step 1: Validate prerequisites
print_step "1/8 Validating prerequisites..."

# Check SSH to production
print_info "Testing SSH connection to production..."
if [ "$DRY_RUN" = true ]; then
    print_dry "ssh ${PRODUCTION_USER}@${PRODUCTION_HOST} echo 'OK'"
else
    if ! ssh -o BatchMode=yes -o ConnectTimeout=5 "${PRODUCTION_USER}@${PRODUCTION_HOST}" "echo 'OK'" > /dev/null 2>&1; then
        print_error "Cannot SSH to production server (${PRODUCTION_USER}@${PRODUCTION_HOST})"
        print_error "Ensure SSH key is set up. See script header for full instructions."
        print_error "Quick check: Does ~/.ssh/id_ed25519 exist? Is your public key in production's authorized_keys?"
        exit 1
    fi
    print_info "SSH connection OK"
fi

# Check production container
print_info "Checking production PostgreSQL container..."
if [ "$DRY_RUN" = true ]; then
    print_dry "ssh ${PRODUCTION_USER}@${PRODUCTION_HOST} docker ps --filter name=${PRODUCTION_CONTAINER}"
else
    if ! ssh "${PRODUCTION_USER}@${PRODUCTION_HOST}" "docker ps --format '{{.Names}}' | grep -q '^${PRODUCTION_CONTAINER}$'"; then
        print_error "Production PostgreSQL container '${PRODUCTION_CONTAINER}' is not running"
        exit 1
    fi
    print_info "Production container OK"
fi

# Check staging container
print_info "Checking staging PostgreSQL container..."
if [ "$DRY_RUN" = true ]; then
    print_dry "docker ps --filter name=${STAGING_CONTAINER}"
else
    if ! docker ps --format '{{.Names}}' | grep -q "^${STAGING_CONTAINER}$"; then
        print_error "Staging PostgreSQL container '${STAGING_CONTAINER}' is not running"
        exit 1
    fi
    print_info "Staging container OK"
fi

# Create backup directory
if [ "$DRY_RUN" = false ]; then
    mkdir -p "$BACKUP_DIR"
fi

# Step 2: Backup staging database
print_step "2/8 Backing up staging database..."
if [ "$SKIP_BACKUP" = true ]; then
    print_warn "Skipping staging backup (--skip-backup)"
elif [ "$DRY_RUN" = true ]; then
    print_dry "docker exec ${STAGING_CONTAINER} pg_dump -U ${DATABASE_USER} -d ${DATABASE_NAME} | gzip > ${STAGING_BACKUP}"
else
    docker exec "$STAGING_CONTAINER" pg_dump -U "$DATABASE_USER" -d "$DATABASE_NAME" 2>/dev/null | gzip > "$STAGING_BACKUP"
    BACKUP_SIZE=$(du -h "$STAGING_BACKUP" | cut -f1)
    print_info "Staging backup created: $STAGING_BACKUP ($BACKUP_SIZE)"
fi

# Step 3: Export production database via SSH
print_step "3/8 Exporting production database..."
if [ "$DRY_RUN" = true ]; then
    print_dry "ssh ${PRODUCTION_USER}@${PRODUCTION_HOST} docker exec ${PRODUCTION_CONTAINER} pg_dump -U ${DATABASE_USER} -d ${DATABASE_NAME} > ${PRODUCTION_DUMP}"
else
    print_info "Streaming production database (this may take a while)..."
    ssh "${PRODUCTION_USER}@${PRODUCTION_HOST}" "docker exec ${PRODUCTION_CONTAINER} pg_dump -U ${DATABASE_USER} -d ${DATABASE_NAME}" > "$PRODUCTION_DUMP"
    DUMP_SIZE=$(du -h "$PRODUCTION_DUMP" | cut -f1)
    print_info "Production dump received: $PRODUCTION_DUMP ($DUMP_SIZE)"
fi

# Step 4: Stop staging backend
print_step "4/8 Stopping staging backend..."
if [ "$DRY_RUN" = true ]; then
    print_dry "docker stop ${STAGING_BACKEND_CONTAINER}"
else
    if docker ps --format '{{.Names}}' | grep -q "^${STAGING_BACKEND_CONTAINER}$"; then
        docker stop "$STAGING_BACKEND_CONTAINER" > /dev/null
        print_info "Staging backend stopped"
    else
        print_warn "Staging backend not running, skipping stop"
    fi
fi

# Step 5: Drop and recreate staging database
print_step "5/8 Recreating staging database..."
if [ "$DRY_RUN" = true ]; then
    print_dry "docker exec ${STAGING_CONTAINER} psql -U ${DATABASE_USER} -c 'DROP DATABASE IF EXISTS ${DATABASE_NAME}'"
    print_dry "docker exec ${STAGING_CONTAINER} psql -U ${DATABASE_USER} -c 'CREATE DATABASE ${DATABASE_NAME}'"
else
    # Terminate existing connections
    docker exec "$STAGING_CONTAINER" psql -U "$DATABASE_USER" -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '${DATABASE_NAME}' AND pid <> pg_backend_pid();" > /dev/null 2>&1 || true

    # Drop and create
    docker exec "$STAGING_CONTAINER" psql -U "$DATABASE_USER" -c "DROP DATABASE IF EXISTS ${DATABASE_NAME}" > /dev/null
    docker exec "$STAGING_CONTAINER" psql -U "$DATABASE_USER" -c "CREATE DATABASE ${DATABASE_NAME}" > /dev/null
    print_info "Staging database recreated"
fi

# Step 6: Import production dump
print_step "6/8 Importing production data..."
if [ "$DRY_RUN" = true ]; then
    print_dry "docker exec -i ${STAGING_CONTAINER} psql -U ${DATABASE_USER} -d ${DATABASE_NAME} < ${PRODUCTION_DUMP}"
else
    print_info "Importing data (this may take a while)..."
    # Import with error suppression for non-critical issues (like role doesn't exist)
    docker exec -i "$STAGING_CONTAINER" psql -U "$DATABASE_USER" -d "$DATABASE_NAME" < "$PRODUCTION_DUMP" 2>&1 | grep -v "^ERROR:  role" || true
    print_info "Import complete"
fi

# Step 7: Restart staging backend
print_step "7/8 Restarting staging backend..."
if [ "$DRY_RUN" = true ]; then
    print_dry "docker start ${STAGING_BACKEND_CONTAINER}"
else
    docker start "$STAGING_BACKEND_CONTAINER" > /dev/null 2>&1 || true
    print_info "Staging backend started"

    # Wait for backend to be healthy
    print_info "Waiting for backend to be ready..."
    for i in {1..30}; do
        if docker exec "$STAGING_BACKEND_CONTAINER" curl -sf http://localhost:3000/api/health > /dev/null 2>&1; then
            print_info "Backend is healthy"
            break
        fi
        if [ $i -eq 30 ]; then
            print_warn "Backend health check timed out (may still be starting)"
        fi
        sleep 2
    done
fi

# Step 8: Verify and cleanup
print_step "8/8 Verifying refresh..."
if [ "$DRY_RUN" = true ]; then
    print_dry "docker exec ${STAGING_CONTAINER} psql -U ${DATABASE_USER} -d ${DATABASE_NAME} -c 'SELECT COUNT(*) FROM information_schema.tables'"
else
    # Get table count
    TABLE_COUNT=$(docker exec "$STAGING_CONTAINER" psql -U "$DATABASE_USER" -d "$DATABASE_NAME" -tAc "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'public'")

    # Get row counts for key tables
    print_info "Database statistics:"
    echo ""
    docker exec "$STAGING_CONTAINER" psql -U "$DATABASE_USER" -d "$DATABASE_NAME" -c "
        SELECT
            schemaname || '.' || relname AS table,
            n_live_tup AS rows
        FROM pg_stat_user_tables
        ORDER BY n_live_tup DESC
        LIMIT 10;
    " 2>/dev/null || true
    echo ""

    # Cleanup dump file
    if [ "$KEEP_DUMP" = false ]; then
        rm -f "$PRODUCTION_DUMP"
        print_info "Production dump cleaned up"
    else
        print_info "Production dump kept at: $PRODUCTION_DUMP"
    fi
fi

# Summary
echo ""
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}  Staging Database Refresh Complete!${NC}"
echo -e "${GREEN}========================================${NC}"
echo ""
if [ "$DRY_RUN" = true ]; then
    print_warn "This was a dry run. No changes were made."
else
    print_info "Production data has been copied to staging"
    print_info "Tables: $TABLE_COUNT"
    if [ "$SKIP_BACKUP" = false ] && [ -f "$STAGING_BACKUP" ]; then
        print_info "Previous staging backup: $STAGING_BACKUP"
    fi
fi
echo ""
