#!/bin/bash
# Simple backup script for your personal cloud

set -e
set -o pipefail

# Parse command line flags
BACKUP_HOME=true
BACKUP_APPS=true
BACKUP_CLUSTER=true

show_help() {
    echo "Usage: $0 [OPTIONS]"
    echo "Backup components of your wild-cloud infrastructure"
    echo ""
    echo "Options:"
    echo "  --home-only       Backup only WC_HOME (wild-cloud configuration)"
    echo "  --apps-only       Backup only applications (databases and PVCs)"
    echo "  --cluster-only    Backup only Kubernetes cluster resources"
    echo "  --no-home         Skip WC_HOME backup"
    echo "  --no-apps         Skip application backups"
    echo "  --no-cluster      Skip cluster resource backup"
    echo "  -h, --help        Show this help message"
    echo ""
    echo "Default: Backup all components (home, apps, cluster)"
}

# Process command line arguments
while [[ $# -gt 0 ]]; do
    case $1 in
        --home-only)
            BACKUP_HOME=true
            BACKUP_APPS=false
            BACKUP_CLUSTER=false
            shift
            ;;
        --apps-only)
            BACKUP_HOME=false
            BACKUP_APPS=true
            BACKUP_CLUSTER=false
            shift
            ;;
        --cluster-only)
            BACKUP_HOME=false
            BACKUP_APPS=false
            BACKUP_CLUSTER=true
            shift
            ;;
        --no-home)
            BACKUP_HOME=false
            shift
            ;;
        --no-apps)
            BACKUP_APPS=false
            shift
            ;;
        --no-cluster)
            BACKUP_CLUSTER=false
            shift
            ;;
        -h|--help)
            show_help
            exit 0
            ;;
        *)
            echo "Unknown option: $1"
            show_help
            exit 1
            ;;
    esac
done

# Initialize Wild Cloud environment
if [ -z "${WC_ROOT}" ]; then
    echo "WC_ROOT is not set."
    exit 1
else
    source "${WC_ROOT}/scripts/common.sh"
    init_wild_env
fi

if `wild-config cloud.backup.root --check`; then
    export RESTIC_REPOSITORY="$(wild-config cloud.backup.root)"
else
    echo "WARNING: Could not get cloud backup root."
    exit 1
fi

if `wild-secret cloud.backupPassword --check`; then
    export RESTIC_PASSWORD="$(wild-secret cloud.backupPassword)"
else
    echo "WARNING: Could not get cloud backup secret."
    exit 1
fi

if `wild-config cloud.backup.staging --check`; then
    STAGING_DIR="$(wild-config cloud.backup.staging)"
else
    echo "WARNING: Could not get cloud backup staging directory."
    exit 1
fi

echo "Backup at '$RESTIC_REPOSITORY'."

# Initialize the repository if needed.
echo "Checking if restic repository exists..."
if restic cat config >/dev/null 2>&1; then
    echo "Using existing backup repository."
else
    echo "No existing backup repository found. Initializing restic repository..."
    restic init
    echo "Repository initialized successfully."
fi

# Backup entire WC_HOME
if [ "$BACKUP_HOME" = true ]; then
    echo "Backing up WC_HOME..."
    restic --verbose --tag wild-cloud --tag wc-home --tag "$(date +%Y-%m-%d)" backup $WC_HOME
    echo "WC_HOME backup completed."
    # TODO: Ignore wild cloud cache?
else
    echo "Skipping WC_HOME backup."
fi

mkdir -p "$STAGING_DIR"

# Run backup for all apps at once
if [ "$BACKUP_APPS" = true ]; then
    echo "Running backup for all apps..."
    wild-app-backup --all

    # Upload each app's backup to restic individually  
    for app_dir in "$STAGING_DIR"/apps/*; do
        if [ ! -d "$app_dir" ]; then
            continue
        fi
        app="$(basename "$app_dir")"
        echo "Uploading backup for app: $app"
        restic --verbose --tag wild-cloud --tag "$app" --tag "$(date +%Y-%m-%d)" backup "$app_dir"
        echo "Backup for app '$app' completed."
    done
else
    echo "Skipping application backups."
fi

# --- etcd Backup Function ----------------------------------------------------
backup_etcd() {
    local cluster_backup_dir="$1"
    local etcd_backup_file="$cluster_backup_dir/etcd-snapshot.db"
    
    echo "Creating etcd snapshot..."
    
    # For Talos, we use talosctl to create etcd snapshots
    if command -v talosctl >/dev/null 2>&1; then
        # Try to get etcd snapshot via talosctl (works for Talos clusters)
        local control_plane_nodes
        control_plane_nodes=$(kubectl get nodes -l node-role.kubernetes.io/control-plane -o jsonpath='{.items[*].status.addresses[?(@.type=="InternalIP")].address}' | tr ' ' '\n' | head -1)
        
        if [[ -n "$control_plane_nodes" ]]; then
            echo "Using talosctl to backup etcd from control plane node: $control_plane_nodes"
            if talosctl --nodes "$control_plane_nodes" etcd snapshot "$etcd_backup_file"; then
                echo "  etcd backup created: $etcd_backup_file"
                return 0
            else
                echo "  talosctl etcd snapshot failed, trying alternative method..."
            fi
        else
            echo "  No control plane nodes found for talosctl method"
        fi
    fi
    
    # Alternative: Try to backup via etcd pod if available
    local etcd_pod
    etcd_pod=$(kubectl get pods -n kube-system -l component=etcd -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || true)
    
    if [[ -n "$etcd_pod" ]]; then
        echo "Using etcd pod: $etcd_pod"
        # Create snapshot using etcdctl inside the etcd pod
        if kubectl exec -n kube-system "$etcd_pod" -- etcdctl \
            --endpoints=https://127.0.0.1:2379 \
            --cacert=/etc/kubernetes/pki/etcd/ca.crt \
            --cert=/etc/kubernetes/pki/etcd/server.crt \
            --key=/etc/kubernetes/pki/etcd/server.key \
            snapshot save /tmp/etcd-snapshot.db; then
            
            # Copy snapshot out of pod
            kubectl cp -n kube-system "$etcd_pod:/tmp/etcd-snapshot.db" "$etcd_backup_file"
            
            # Clean up temporary file in pod
            kubectl exec -n kube-system "$etcd_pod" -- rm -f /tmp/etcd-snapshot.db
            
            echo "  etcd backup created: $etcd_backup_file"
            return 0
        else
            echo "  etcd pod snapshot failed"
        fi
    else
        echo "  No etcd pod found in kube-system namespace"
    fi
    
    # Final fallback: Try direct etcdctl if available on local system
    if command -v etcdctl >/dev/null 2>&1; then
        echo "Attempting local etcdctl backup..."
        # This would need proper certificates and endpoints configured
        echo "  Local etcdctl backup not implemented (requires certificate configuration)"
    fi
    
    echo "  Warning: Could not create etcd backup - no working method found"
    echo "  Consider installing talosctl or ensuring etcd pods are accessible"
    return 1
}

# Back up Kubernetes cluster resources
if [ "$BACKUP_CLUSTER" = true ]; then
    echo "Backing up Kubernetes cluster resources..."
    CLUSTER_BACKUP_DIR="$STAGING_DIR/cluster"
    
    # Clean up any existing cluster backup files
    if [[ -d "$CLUSTER_BACKUP_DIR" ]]; then
        echo "Cleaning up existing cluster backup files..."
        rm -rf "$CLUSTER_BACKUP_DIR"
    fi
    mkdir -p "$CLUSTER_BACKUP_DIR"

    kubectl get all -A -o yaml > "$CLUSTER_BACKUP_DIR/all-resources.yaml"
    kubectl get secrets -A -o yaml > "$CLUSTER_BACKUP_DIR/secrets.yaml"
    kubectl get configmaps -A -o yaml > "$CLUSTER_BACKUP_DIR/configmaps.yaml"
    kubectl get persistentvolumes -o yaml > "$CLUSTER_BACKUP_DIR/persistentvolumes.yaml"
    kubectl get persistentvolumeclaims -A -o yaml > "$CLUSTER_BACKUP_DIR/persistentvolumeclaims.yaml"
    kubectl get storageclasses -o yaml > "$CLUSTER_BACKUP_DIR/storageclasses.yaml"

    echo "Backing up etcd..."
    backup_etcd "$CLUSTER_BACKUP_DIR"

    echo "Cluster resources backed up to $CLUSTER_BACKUP_DIR"

    # Upload cluster backup to restic
    echo "Uploading cluster backup to restic..."
    restic --verbose --tag wild-cloud --tag cluster --tag "$(date +%Y-%m-%d)" backup "$CLUSTER_BACKUP_DIR"
    echo "Cluster backup completed."
else
    echo "Skipping cluster backup."
fi

echo "Backup completed: $BACKUP_DIR"
