#!/bin/bash

# Cloud SQL Cross-Project Restore Script
# This script restores a Cloud SQL instance from a source project to a target project

set -e  # Exit on any error

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

# Function to print colored output (portable across shells)
print_status() {
    printf "%b\n" "${BLUE}[INFO]${NC} $1"
}

print_success() {
    printf "%b\n" "${GREEN}[SUCCESS]${NC} $1"
}

print_warning() {
    printf "%b\n" "${YELLOW}[WARNING]${NC} $1"
}

print_error() {
    printf "%b\n" "${RED}[ERROR]${NC} $1"
}

# Function to display usage
usage() {
    echo "Usage: $0 [OPTIONS]"
    echo ""
    echo "Options:"
    echo "  -s, --source-instance    Source instance name (required)"
    echo "  -p, --source-project     Source project ID (required)"
    echo "  -t, --target-instance    Target instance name (required)"
    echo "  -P, --target-project     Target project ID (required)"
    echo "  -c, --create-backup      Create on-demand backup before restore (optional)"
    echo "  -b, --backup-id          Specific backup ID to restore from (optional)"
    echo "  -h, --help               Display this help message"
    echo ""
    echo "Example:"
    echo "  $0 -s dev-postgresql -p appcircle -t dev-postgresql-new -P target-project"
    echo "  $0 -s dev-postgresql -p appcircle -t dev-postgresql-new -P target-project -c"
    echo "  $0 -s dev-postgresql -p appcircle -t dev-postgresql-new -P target-project -b 1754391600000"
}

# Function to check if gcloud is installed and authenticated
check_prerequisites() {
    print_status "Checking prerequisites..."
    
    if ! command -v gcloud &> /dev/null; then
        print_error "gcloud CLI is not installed. Please install it first."
        exit 1
    fi
    
    if ! gcloud auth list --filter=status:ACTIVE --format="value(account)" | grep -q .; then
        print_error "Not authenticated with gcloud. Please run 'gcloud auth login' first."
        exit 1
    fi
    
    print_success "Prerequisites check passed"
}

# Function to validate parameters
validate_parameters() {
    if [[ -z "$SOURCE_INSTANCE" ]]; then
        print_error "Source instance name is required"
        usage
        exit 1
    fi
    
    if [[ -z "$SOURCE_PROJECT" ]]; then
        print_error "Source project ID is required"
        usage
        exit 1
    fi
    
    if [[ -z "$TARGET_INSTANCE" ]]; then
        print_error "Target instance name is required"
        usage
        exit 1
    fi
    
    if [[ -z "$TARGET_PROJECT" ]]; then
        print_error "Target project ID is required"
        usage
        exit 1
    fi
    
    print_success "Parameters validated"
}

# Function to check if source instance exists
check_source_instance() {
    print_status "Checking if source instance exists..."
    
    if ! gcloud sql instances describe "$SOURCE_INSTANCE" --project="$SOURCE_PROJECT" &> /dev/null; then
        print_error "Source instance '$SOURCE_INSTANCE' not found in project '$SOURCE_PROJECT'"
        exit 1
    fi
    
    print_success "Source instance found"
}

 

# Function to check if target instance exists
check_target_instance() {
    print_status "Checking if target instance exists..."
    
    if ! gcloud sql instances describe "$TARGET_INSTANCE" --project="$TARGET_PROJECT" &> /dev/null; then
        print_error "Target instance '$TARGET_INSTANCE' not found in project '$TARGET_PROJECT'"
        print_error "Please create the target instance before running this script"
        exit 1
    else
        print_success "Target instance found"
    fi
}

# Function to create on-demand backup
create_backup() {
    if [[ "$CREATE_BACKUP" == "true" ]]; then
        print_status "Creating on-demand backup for source instance..."
        
        BACKUP_NAME="manual-backup-$(date +%Y%m%d-%H%M%S)"
        
        gcloud sql backups create \
            --async \
            --instance="$SOURCE_INSTANCE" \
            --project="$SOURCE_PROJECT" \
            --description="Manual backup created by restore script" \
            --backup-name="$BACKUP_NAME"
        
        print_success "Backup creation initiated: $BACKUP_NAME"
        print_warning "Waiting for backup to complete..."
        
        # Wait for backup to complete
        while true; do
            STATUS=$(gcloud sql backups list \
                --instance="$SOURCE_INSTANCE" \
                --project="$SOURCE_PROJECT" \
                --filter="name:$BACKUP_NAME" \
                --format="value(status)")
            
            if [[ "$STATUS" == "SUCCESSFUL" ]]; then
                print_success "Backup completed successfully"
                break
            elif [[ "$STATUS" == "FAILED" ]]; then
                print_error "Backup failed"
                exit 1
            else
                print_status "Backup status: $STATUS. Waiting..."
                sleep 30
            fi
        done
    fi
}

# Function to get backup ID
get_backup_id() {
    if [[ -n "$BACKUP_ID" ]]; then
        print_status "Using specified backup ID: $BACKUP_ID"
        return
    fi
    
    print_status "Finding the latest successful backup..."
    
    BACKUP_ID=$(gcloud sql backups list \
        --instance="$SOURCE_INSTANCE" \
        --project="$SOURCE_PROJECT" \
        --sort-by=~window_start_time \
        --filter=status=successful \
        --limit=1 \
        --format="value(id)")
    
    if [[ -z "$BACKUP_ID" ]]; then
        print_error "No successful backups found for instance '$SOURCE_INSTANCE'"
        exit 1
    fi
    
    print_success "Found backup ID: $BACKUP_ID"
}

# Function to perform the restore
perform_restore() {
    print_status "Starting restore process..."
    print_status "Source: $SOURCE_INSTANCE ($SOURCE_PROJECT)"
    print_status "Target: $TARGET_INSTANCE ($TARGET_PROJECT)"
    print_status "Backup ID: $BACKUP_ID"
    
    printf "%b" "${YELLOW}[WARNING]${NC} This operation will overwrite the target instance. Are you sure? (y/N): "
    read -r response
    
    if [[ ! "$response" =~ ^[Yy]$ ]]; then
        print_status "Restore cancelled by user"
        exit 0
    fi
    
    print_status "Initiating restore..."
    
    gcloud sql backups restore "$BACKUP_ID" \
        --project="$TARGET_PROJECT" \
        --restore-instance="$TARGET_INSTANCE" \
        --backup-instance="$SOURCE_INSTANCE" \
        --backup-project="$SOURCE_PROJECT"
    
    print_success "Restore operation initiated successfully"
    print_status "You can monitor the progress with:"
    echo "  gcloud sql operations list --instance=$TARGET_INSTANCE --project=$TARGET_PROJECT"
}

# Main script execution
main() {
    echo "=========================================="
    echo "Cloud SQL Cross-Project Restore Script"
    echo "=========================================="
    echo ""
    
    # Parse command line arguments
    while [[ $# -gt 0 ]]; do
        case $1 in
            -s|--source-instance)
                SOURCE_INSTANCE="$2"
                shift 2
                ;;
            -p|--source-project)
                SOURCE_PROJECT="$2"
                shift 2
                ;;
            -t|--target-instance)
                TARGET_INSTANCE="$2"
                shift 2
                ;;
            -P|--target-project)
                TARGET_PROJECT="$2"
                shift 2
                ;;
            -c|--create-backup)
                CREATE_BACKUP="true"
                shift
                ;;
            -b|--backup-id)
                BACKUP_ID="$2"
                shift 2
                ;;
            -h|--help)
                usage
                exit 0
                ;;
            *)
                print_error "Unknown option: $1"
                usage
                exit 1
                ;;
        esac
    done
    
    # Validate parameters
    validate_parameters
    
    # Check prerequisites
    check_prerequisites
    
    # Check instances
    check_source_instance
    check_target_instance
    
    # Create backup if requested
    create_backup
    
    # Get backup ID
    get_backup_id
    
    # Perform restore
    perform_restore
    
    echo ""
    print_success "Script completed successfully!"
}

# Run main function with all arguments
main "$@"