#!/bin/bash

# End-to-End OADP Hook Testing Script
# Orchestrates all existing scripts to perform complete backup/restore hook verification
# This script assumes an active OpenShift/Kubernetes session

set -e

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

# Default values
APP_NAME="mysql-hooks-e2e"
APP_NAMESPACE="test-oadp-xx"
BACKUP_NAME="${APP_NAME}-backup"
RESTORE_NAME="${APP_NAME}-restore"
RESTORE_NAMESPACE="${APP_NAMESPACE}-restored"
APP_TYPE="mysql"
REPLICAS=2
VELERO_NAMESPACE="openshift-adp"
CLEANUP_ON_EXIT=true
VERBOSE=false
SKIP_DEPLOY=false
SKIP_BACKUP=false
SKIP_RESTORE=false

# Test results tracking
TEST_RESULTS=()
TOTAL_TESTS=0
PASSED_TESTS=0
FAILED_TESTS=0

usage() {
    cat << EOF
Usage: $0 [options]

This script performs a complete end-to-end test of OADP backup/restore hooks:
1. Cleanup existing namespaces
2. Deploy sample application
3. Run backup verification with hooks
4. Cleanup original namespace
5. Run restore verification with hooks
6. Provide comprehensive test summary

Options:
    -a, --app-name <name>        Name of the application (default: mysql-hooks-e2e)
    -n, --namespace <ns>         Original app namespace (default: test-oadp-xx)
    -r, --restore-namespace <ns> Restore target namespace (default: test-oadp-xx-restored)
    -t, --type <type>            App type: mysql, nginx, or generic (default: mysql)
    --replicas <count>           Number of app replicas (default: 2)
    --velero-namespace <ns>      Velero namespace (default: openshift-adp)
    --no-cleanup                 Don't cleanup namespaces on exit
    --skip-deploy               Skip application deployment step
    --skip-backup               Skip backup verification step
    --skip-restore              Skip restore verification step
    -v, --verbose               Enable verbose output
    -h, --help                  Show this help message

Examples:
    # Run full test with defaults
    $0

    # Test nginx app with 3 replicas
    $0 -t nginx --replicas 3 -a my-nginx-test

    # Skip deployment and only test backup/restore
    $0 --skip-deploy -a existing-app

    # Verbose output with custom namespaces
    $0 -v -n my-test-ns -r my-restore-ns
EOF
}

log() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

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

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

success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

step() {
    echo -e "${PURPLE}[STEP]${NC} $1"
}

result() {
    echo -e "${CYAN}[RESULT]${NC} $1"
}

# Function to record test results
record_test() {
    local test_name="$1"
    local status="$2"
    local details="$3"
    
    TEST_RESULTS+=("$test_name|$status|$details")
    TOTAL_TESTS=$((TOTAL_TESTS + 1))
    
    if [[ "$status" == "PASS" ]]; then
        PASSED_TESTS=$((PASSED_TESTS + 1))
        success "Test: $test_name - PASSED"
    else
        FAILED_TESTS=$((FAILED_TESTS + 1))
        error "Test: $test_name - FAILED: $details"
    fi
}

# Parse command line arguments
while [[ $# -gt 0 ]]; do
    case $1 in
        -a|--app-name)
            APP_NAME="$2"
            BACKUP_NAME="${APP_NAME}-backup"
            RESTORE_NAME="${APP_NAME}-restore"
            shift 2
            ;;
        -n|--namespace)
            APP_NAMESPACE="$2"
            shift 2
            ;;
        -r|--restore-namespace)
            RESTORE_NAMESPACE="$2"
            shift 2
            ;;
        -t|--type)
            APP_TYPE="$2"
            shift 2
            ;;
        --replicas)
            REPLICAS="$2"
            shift 2
            ;;
        --velero-namespace)
            VELERO_NAMESPACE="$2"
            shift 2
            ;;
        --no-cleanup)
            CLEANUP_ON_EXIT=false
            shift
            ;;
        --skip-deploy)
            SKIP_DEPLOY=true
            shift
            ;;
        --skip-backup)
            SKIP_BACKUP=true
            shift
            ;;
        --skip-restore)
            SKIP_RESTORE=true
            shift
            ;;
        -v|--verbose)
            VERBOSE=true
            shift
            ;;
        -h|--help)
            usage
            exit 0
            ;;
        *)
            error "Unknown option: $1"
            usage
            exit 1
            ;;
    esac
done

# Check if kubectl/oc is available
if command -v oc &> /dev/null; then
    KUBECTL_CMD="oc"
elif command -v kubectl &> /dev/null; then
    KUBECTL_CMD="kubectl"
else
    error "Neither 'oc' nor 'kubectl' command found. Please install one of them."
    exit 1
fi

# Check if velero CLI is available
if ! command -v velero &> /dev/null; then
    error "Velero CLI not found. Please install velero CLI."
    exit 1
fi

# Verify required scripts exist
REQUIRED_SCRIPTS=("deploy-app.sh" "verify-backup-hook.sh" "verify-restore-hook.sh")
for script in "${REQUIRED_SCRIPTS[@]}"; do
    if [[ ! -f "$script" ]]; then
        error "Required script not found: $script"
        exit 1
    fi
    if [[ ! -x "$script" ]]; then
        warn "Making $script executable"
        chmod +x "$script"
    fi
done

log "Using kubectl command: $KUBECTL_CMD"
log "Application: $APP_NAME"
log "App Type: $APP_TYPE"
log "Replicas: $REPLICAS"
log "Original Namespace: $APP_NAMESPACE"
log "Restore Namespace: $RESTORE_NAMESPACE"
log "Velero Namespace: $VELERO_NAMESPACE"

# Cleanup function
cleanup() {
    if [[ "$CLEANUP_ON_EXIT" == true ]]; then
        log "Performing cleanup..."
        
        # Delete backup
        if velero backup describe "$BACKUP_NAME" --namespace="$VELERO_NAMESPACE" &> /dev/null; then
            log "Deleting backup: $BACKUP_NAME"
            velero backup delete "$BACKUP_NAME" --namespace="$VELERO_NAMESPACE" --confirm || warn "Failed to delete backup"
        fi
        
        # Delete restore
        if velero restore describe "$RESTORE_NAME" --namespace="$VELERO_NAMESPACE" &> /dev/null; then
            log "Deleting restore: $RESTORE_NAME"
            velero restore delete "$RESTORE_NAME" --namespace="$VELERO_NAMESPACE" --confirm || warn "Failed to delete restore"
        fi
        
        # Delete namespaces
        for ns in "$APP_NAMESPACE" "$RESTORE_NAMESPACE"; do
            if $KUBECTL_CMD get namespace "$ns" &> /dev/null; then
                log "Deleting namespace: $ns"
                $KUBECTL_CMD delete namespace "$ns" --ignore-not-found=true || warn "Failed to delete namespace $ns"
            fi
        done
    fi
}

# Set up cleanup trap
trap cleanup EXIT

# Function to wait for namespace deletion
wait_for_namespace_deletion() {
    local namespace="$1"
    local max_attempts=30
    
    if ! $KUBECTL_CMD get namespace "$namespace" &> /dev/null; then
        return 0
    fi
    
    log "Waiting for namespace $namespace to be deleted..."
    for i in $(seq 1 $max_attempts); do
        if ! $KUBECTL_CMD get namespace "$namespace" &> /dev/null; then
            success "Namespace $namespace deleted"
            return 0
        fi
        log "Waiting for namespace deletion... ($i/$max_attempts)"
        sleep 10
    done
    
    warn "Namespace $namespace still exists after waiting"
    return 1
}

# Step 1: Cleanup existing namespaces
step "Step 1: Cleaning up existing namespaces"
for ns in "$APP_NAMESPACE" "$RESTORE_NAMESPACE"; do
    if $KUBECTL_CMD get namespace "$ns" &> /dev/null; then
        log "Deleting existing namespace: $ns"
        $KUBECTL_CMD delete namespace "$ns" --ignore-not-found=true
        wait_for_namespace_deletion "$ns"
    else
        log "Namespace $ns does not exist, skipping cleanup"
    fi
done

# Delete existing backup/restore if they exist
if velero backup describe "$BACKUP_NAME" --namespace="$VELERO_NAMESPACE" &> /dev/null; then
    log "Deleting existing backup: $BACKUP_NAME"
    velero backup delete "$BACKUP_NAME" --namespace="$VELERO_NAMESPACE" --confirm
fi

if velero restore describe "$RESTORE_NAME" --namespace="$VELERO_NAMESPACE" &> /dev/null; then
    log "Deleting existing restore: $RESTORE_NAME"
    velero restore delete "$RESTORE_NAME" --namespace="$VELERO_NAMESPACE" --confirm
fi

record_test "Namespace Cleanup" "PASS" "Successfully cleaned up existing resources"

# Step 2: Deploy sample application
if [[ "$SKIP_DEPLOY" == false ]]; then
    step "Step 2: Deploying sample application"
    
    DEPLOY_CMD="./deploy-app.sh -a $APP_NAME -n $APP_NAMESPACE -t $APP_TYPE -r $REPLICAS"
    if [[ "$VERBOSE" == true ]]; then
        DEPLOY_CMD="$DEPLOY_CMD -v"
    fi
    
    log "Executing: $DEPLOY_CMD"
    if eval "$DEPLOY_CMD"; then
        record_test "Application Deployment" "PASS" "Successfully deployed $APP_TYPE application with $REPLICAS replicas"
        
        # Verify pods are running
        sleep 10
        RUNNING_PODS=$($KUBECTL_CMD get pods -n "$APP_NAMESPACE" --no-headers | grep -c "Running" || echo "0")
        if [[ "$RUNNING_PODS" -eq "$REPLICAS" ]]; then
            record_test "Pod Readiness" "PASS" "All $REPLICAS pods are running"
        else
            record_test "Pod Readiness" "FAIL" "Only $RUNNING_PODS out of $REPLICAS pods are running"
        fi
    else
        record_test "Application Deployment" "FAIL" "Failed to deploy application"
        error "Application deployment failed, exiting"
        exit 1
    fi
else
    step "Step 2: Skipping application deployment (--skip-deploy specified)"
    
    # Verify existing application
    if $KUBECTL_CMD get namespace "$APP_NAMESPACE" &> /dev/null; then
        EXISTING_PODS=$($KUBECTL_CMD get pods -n "$APP_NAMESPACE" --no-headers | wc -l || echo "0")
        record_test "Existing Application Check" "PASS" "Found existing application with $EXISTING_PODS pods"
    else
        record_test "Existing Application Check" "FAIL" "No existing application found"
        error "No existing application found and deployment skipped"
        exit 1
    fi
fi

# Step 3: Run backup verification
if [[ "$SKIP_BACKUP" == false ]]; then
    step "Step 3: Running backup verification with hooks"
    
    BACKUP_CMD="./verify-backup-hook.sh -b $BACKUP_NAME -a $APP_NAMESPACE -n $VELERO_NAMESPACE -p $REPLICAS -c"
    if [[ "$VERBOSE" == true ]]; then
        BACKUP_CMD="$BACKUP_CMD -v"
    fi
    
    log "Executing: $BACKUP_CMD"
    if eval "$BACKUP_CMD"; then
        record_test "Backup Creation and Verification" "PASS" "Backup created and hook verification completed"
    else
        record_test "Backup Creation and Verification" "FAIL" "Backup creation or verification failed"
        error "Backup verification failed, continuing with restore test..."
    fi
else
    step "Step 3: Skipping backup verification (--skip-backup specified)"
fi

# Step 4: Remove original application namespace
step "Step 4: Removing original application namespace"
if $KUBECTL_CMD get namespace "$APP_NAMESPACE" &> /dev/null; then
    log "Deleting namespace: $APP_NAMESPACE"
    $KUBECTL_CMD delete namespace "$APP_NAMESPACE"
    wait_for_namespace_deletion "$APP_NAMESPACE"
    record_test "Original Namespace Deletion" "PASS" "Successfully deleted original namespace"
else
    record_test "Original Namespace Deletion" "PASS" "Original namespace already deleted"
fi

# Step 5: Run restore verification
if [[ "$SKIP_RESTORE" == false ]]; then
    step "Step 5: Running restore verification with hooks"
    
    RESTORE_CMD="./verify-restore-hook.sh -r $RESTORE_NAME -b $BACKUP_NAME -t $RESTORE_NAMESPACE -n $VELERO_NAMESPACE -p $REPLICAS -c"
    if [[ "$VERBOSE" == true ]]; then
        RESTORE_CMD="$RESTORE_CMD -v"
    fi
    
    log "Executing: $RESTORE_CMD"
    if eval "$RESTORE_CMD"; then
        record_test "Restore Creation and Verification" "PASS" "Restore created and hook verification completed"
        
        # Verify restored pods
        sleep 15
        if $KUBECTL_CMD get namespace "$RESTORE_NAMESPACE" &> /dev/null; then
            RESTORED_PODS=$($KUBECTL_CMD get pods -n "$RESTORE_NAMESPACE" --no-headers | grep -c "Running" || echo "0")
            if [[ "$RESTORED_PODS" -eq "$REPLICAS" ]]; then
                record_test "Restored Pod Verification" "PASS" "All $REPLICAS pods restored and running"
            else
                record_test "Restored Pod Verification" "FAIL" "Only $RESTORED_PODS out of $REPLICAS pods restored"
            fi
        else
            record_test "Restored Pod Verification" "FAIL" "Restore namespace not found"
        fi
    else
        record_test "Restore Creation and Verification" "FAIL" "Restore creation or verification failed"
    fi
else
    step "Step 5: Skipping restore verification (--skip-restore specified)"
fi

# Step 6: Comprehensive summary
step "Step 6: Test Summary and Results"

echo ""
echo "======================================================================"
echo "                    OADP HOOK TESTING SUMMARY"
echo "======================================================================"
echo ""

result "Test Configuration:"
result "  Application: $APP_NAME ($APP_TYPE)"
result "  Replicas: $REPLICAS"
result "  Original Namespace: $APP_NAMESPACE"
result "  Restore Namespace: $RESTORE_NAMESPACE"
result "  Backup Name: $BACKUP_NAME"
result "  Restore Name: $RESTORE_NAME"
result "  Velero Namespace: $VELERO_NAMESPACE"

echo ""
result "Test Results Overview:"
result "  Total Tests: $TOTAL_TESTS"
result "  Passed: $PASSED_TESTS"
result "  Failed: $FAILED_TESTS"

echo ""
result "Detailed Test Results:"
for test_result in "${TEST_RESULTS[@]}"; do
    IFS='|' read -r test_name status details <<< "$test_result"
    if [[ "$status" == "PASS" ]]; then
        result "  ✓ $test_name: $details"
    else
        result "  ✗ $test_name: $details"
    fi
done

echo ""
if [[ $FAILED_TESTS -eq 0 ]]; then
    success "All tests passed! OADP hook functionality is working correctly."
    result "Final Status: SUCCESS"
    echo ""
    result "No hook counting bugs detected in this environment."
else
    error "Some tests failed. OADP hook functionality may have issues."
    result "Final Status: FAILURE"
    echo ""
    result "Hook counting bugs may be present. Review the detailed results above."
fi

echo ""
result "Cleanup Status:"
if [[ "$CLEANUP_ON_EXIT" == true ]]; then
    result "  Automatic cleanup will be performed on script exit"
else
    result "  Manual cleanup required (--no-cleanup specified)"
    result "  To cleanup manually:"
    result "    velero backup delete $BACKUP_NAME --confirm"
    result "    velero restore delete $RESTORE_NAME --confirm"
    result "    $KUBECTL_CMD delete namespace $RESTORE_NAMESPACE"
fi

echo ""
echo "======================================================================"

# Exit with appropriate code
if [[ $FAILED_TESTS -eq 0 ]]; then
    exit 0
else
    exit 1
fi