#!/bin/bash

# Deploy Sample App for Velero Hook Testing
# Creates a sample application with 2 pods to test backup/restore hook counting

set -e

# 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

# Default values
APP_NAME="mysql-hooks-e2e"
NAMESPACE="test-oadp-xx"
REPLICAS=2
APP_TYPE="mysql"  # mysql, nginx, or generic
CREATE_PVC=true
WAIT_READY=true
VERBOSE=false

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

Options:
    -a, --app-name <name>      Name of the application (default: mysql-hooks-e2e)
    -n, --namespace <ns>       Namespace to deploy to (default: test-oadp-xx)
    -r, --replicas <count>     Number of replicas/pods (default: 2)
    -t, --type <type>          App type: mysql, nginx, or generic (default: mysql)
    --no-pvc                   Don't create PersistentVolumeClaim
    --no-wait                  Don't wait for pods to be ready
    -v, --verbose              Enable verbose output
    -h, --help                 Show this help message

Examples:
    # Deploy MySQL app with default settings
    $0

    # Deploy nginx app with 3 replicas
    $0 -t nginx -r 3 -a my-nginx-app

    # Deploy to custom namespace
    $0 -n my-test-namespace -a test-app

    # Deploy without persistent storage
    $0 --no-pvc
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"
}

# Parse command line arguments
while [[ $# -gt 0 ]]; do
    case $1 in
        -a|--app-name)
            APP_NAME="$2"
            shift 2
            ;;
        -n|--namespace)
            NAMESPACE="$2"
            shift 2
            ;;
        -r|--replicas)
            REPLICAS="$2"
            shift 2
            ;;
        -t|--type)
            APP_TYPE="$2"
            shift 2
            ;;
        --no-pvc)
            CREATE_PVC=false
            shift
            ;;
        --no-wait)
            WAIT_READY=false
            shift
            ;;
        -v|--verbose)
            VERBOSE=true
            shift
            ;;
        -h|--help)
            usage
            exit 0
            ;;
        *)
            error "Unknown option: $1"
            usage
            exit 1
            ;;
    esac
done

# Validate app type
if [[ ! "$APP_TYPE" =~ ^(mysql|nginx|generic)$ ]]; then
    error "Invalid app type: $APP_TYPE. Must be mysql, nginx, or generic"
    exit 1
fi

# 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

log "Using kubectl command: $KUBECTL_CMD"
log "Deploying app: $APP_NAME"
log "Namespace: $NAMESPACE"
log "App type: $APP_TYPE"
log "Replicas: $REPLICAS"

# Create namespace if it doesn't exist
create_namespace() {
    log "Creating namespace: $NAMESPACE"
    
    if $KUBECTL_CMD get namespace "$NAMESPACE" &> /dev/null; then
        warn "Namespace $NAMESPACE already exists"
    else
        $KUBECTL_CMD create namespace "$NAMESPACE"
        success "Namespace $NAMESPACE created"
    fi
}

# Create PVC if requested
create_pvc() {
    if [[ "$CREATE_PVC" == false ]]; then
        log "Skipping PVC creation"
        return 0
    fi
    
    log "Creating PersistentVolumeClaim..."
    
    cat << EOF | $KUBECTL_CMD apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ${APP_NAME}-pvc
  namespace: $NAMESPACE
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
EOF
    
    success "PVC ${APP_NAME}-pvc created"
}

# Deploy MySQL application
deploy_mysql() {
    log "Deploying MySQL application..."
    
    # MySQL Secret
    cat << EOF | $KUBECTL_CMD apply -f -
apiVersion: v1
kind: Secret
metadata:
  name: ${APP_NAME}-secret
  namespace: $NAMESPACE
type: Opaque
data:
  mysql-root-password: $(echo -n 'rootpassword123' | base64)
  mysql-password: $(echo -n 'userpassword123' | base64)
  mysql-user: $(echo -n 'testuser' | base64)
  mysql-database: $(echo -n 'testdb' | base64)
EOF

    # MySQL ConfigMap
    cat << EOF | $KUBECTL_CMD apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
  name: ${APP_NAME}-config
  namespace: $NAMESPACE
data:
  my.cnf: |
    [mysqld]
    bind-address = 0.0.0.0
    port = 3306
    datadir = /var/lib/mysql
    socket = /var/lib/mysql/mysql.sock
    pid-file = /var/run/mysqld/mysqld.pid
    
    # Basic settings
    default-storage-engine = innodb
    innodb_buffer_pool_size = 128M
    max_connections = 100
    
    # Binary logging
    log-bin = mysql-bin
    server-id = 1
EOF

    # MySQL Deployment
    VOLUME_MOUNTS=""
    VOLUMES=""
    
    if [[ "$CREATE_PVC" == true ]]; then
        VOLUME_MOUNTS="
        - name: mysql-storage
          mountPath: /var/lib/mysql"
        VOLUMES="
      - name: mysql-storage
        persistentVolumeClaim:
          claimName: ${APP_NAME}-pvc"
    else
        VOLUME_MOUNTS="
        - name: mysql-storage
          mountPath: /var/lib/mysql"
        VOLUMES="
      - name: mysql-storage
        emptyDir: {}"
    fi

    cat << EOF | $KUBECTL_CMD apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: $APP_NAME
  namespace: $NAMESPACE
  labels:
    app: $APP_NAME
    type: mysql
spec:
  replicas: $REPLICAS
  selector:
    matchLabels:
      app: $APP_NAME
  template:
    metadata:
      labels:
        app: $APP_NAME
        type: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:8.0
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: ${APP_NAME}-secret
              key: mysql-root-password
        - name: MYSQL_USER
          valueFrom:
            secretKeyRef:
              name: ${APP_NAME}-secret
              key: mysql-user
        - name: MYSQL_PASSWORD
          valueFrom:
            secretKeyRef:
              name: ${APP_NAME}-secret
              key: mysql-password
        - name: MYSQL_DATABASE
          valueFrom:
            secretKeyRef:
              name: ${APP_NAME}-secret
              key: mysql-database
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:$VOLUME_MOUNTS
        - name: config-volume
          mountPath: /etc/mysql/conf.d
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"
        # Add common shell tools for hook execution
        command: ["/bin/bash"]
        args: 
        - -c
        - |
          # Install basic tools
          apt-get update && apt-get install -y procps curl wget
          # Start MySQL
          exec docker-entrypoint.sh mysqld
        livenessProbe:
          exec:
            command:
            - mysqladmin
            - ping
            - -h
            - localhost
            - -u
            - root
            - -p\$MYSQL_ROOT_PASSWORD
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 5
        readinessProbe:
          exec:
            command:
            - mysql
            - -h
            - localhost
            - -u
            - root
            - -p\$MYSQL_ROOT_PASSWORD
            - -e
            - "SELECT 1"
          initialDelaySeconds: 5
          periodSeconds: 2
          timeoutSeconds: 1
      volumes:$VOLUMES
      - name: config-volume
        configMap:
          name: ${APP_NAME}-config
EOF

    # MySQL Service
    cat << EOF | $KUBECTL_CMD apply -f -
apiVersion: v1
kind: Service
metadata:
  name: ${APP_NAME}-service
  namespace: $NAMESPACE
  labels:
    app: $APP_NAME
spec:
  selector:
    app: $APP_NAME
  ports:
  - port: 3306
    targetPort: 3306
    name: mysql
  type: ClusterIP
EOF
}

# Deploy nginx application  
deploy_nginx() {
    log "Deploying nginx application..."
    
    # Nginx ConfigMap
    cat << EOF | $KUBECTL_CMD apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
  name: ${APP_NAME}-config
  namespace: $NAMESPACE
data:
  nginx.conf: |
    events {
        worker_connections 1024;
    }
    http {
        server {
            listen 80;
            server_name localhost;
            
            location / {
                root /usr/share/nginx/html;
                index index.html;
            }
            
            location /health {
                access_log off;
                return 200 "healthy\n";
                add_header Content-Type text/plain;
            }
        }
    }
  index.html: |
    <!DOCTYPE html>
    <html>
    <head>
        <title>Velero Hook Test App</title>
    </head>
    <body>
        <h1>Hello from ${APP_NAME}</h1>
        <p>This is a test application for Velero backup/restore hook testing.</p>
        <p>Pod: <span id="hostname"></span></p>
        <script>
            document.getElementById('hostname').textContent = window.location.hostname;
        </script>
    </body>
    </html>
EOF

    # Nginx Deployment
    VOLUME_MOUNTS=""
    VOLUMES=""
    
    if [[ "$CREATE_PVC" == true ]]; then
        VOLUME_MOUNTS="
        - name: data-storage
          mountPath: /usr/share/nginx/html/data"
        VOLUMES="
      - name: data-storage
        persistentVolumeClaim:
          claimName: ${APP_NAME}-pvc"
    fi

    cat << EOF | $KUBECTL_CMD apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: $APP_NAME
  namespace: $NAMESPACE
  labels:
    app: $APP_NAME
    type: nginx
spec:
  replicas: $REPLICAS
  selector:
    matchLabels:
      app: $APP_NAME
  template:
    metadata:
      labels:
        app: $APP_NAME
        type: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.21
        ports:
        - containerPort: 80
          name: http
        volumeMounts:
        - name: config-volume
          mountPath: /etc/nginx/nginx.conf
          subPath: nginx.conf
        - name: html-volume
          mountPath: /usr/share/nginx/html/index.html
          subPath: index.html$VOLUME_MOUNTS
        resources:
          requests:
            memory: "64Mi"
            cpu: "100m"
          limits:
            memory: "128Mi"
            cpu: "200m"
        livenessProbe:
          httpGet:
            path: /health
            port: 80
          initialDelaySeconds: 10
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /health
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 5
      volumes:
      - name: config-volume
        configMap:
          name: ${APP_NAME}-config
      - name: html-volume
        configMap:
          name: ${APP_NAME}-config$VOLUMES
EOF

    # Nginx Service
    cat << EOF | $KUBECTL_CMD apply -f -
apiVersion: v1
kind: Service
metadata:
  name: ${APP_NAME}-service
  namespace: $NAMESPACE
  labels:
    app: $APP_NAME
spec:
  selector:
    app: $APP_NAME
  ports:
  - port: 80
    targetPort: 80
    name: http
  type: ClusterIP
EOF
}

# Deploy generic application
deploy_generic() {
    log "Deploying generic application..."
    
    # Generic Deployment with busybox
    VOLUME_MOUNTS=""
    VOLUMES=""
    
    if [[ "$CREATE_PVC" == true ]]; then
        VOLUME_MOUNTS="
        - name: data-storage
          mountPath: /data"
        VOLUMES="
      - name: data-storage
        persistentVolumeClaim:
          claimName: ${APP_NAME}-pvc"
    else
        VOLUME_MOUNTS="
        - name: data-storage
          mountPath: /data"
        VOLUMES="
      - name: data-storage
        emptyDir: {}"
    fi

    cat << EOF | $KUBECTL_CMD apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: $APP_NAME
  namespace: $NAMESPACE
  labels:
    app: $APP_NAME
    type: generic
spec:
  replicas: $REPLICAS
  selector:
    matchLabels:
      app: $APP_NAME
  template:
    metadata:
      labels:
        app: $APP_NAME
        type: generic
      annotations:
        post.hook.restore.velero.io/container: app
        post.hook.restore.velero.io/command: '["/bin/sh", "-c", "echo Restore hook 1: SUCCESSFUL at \$(date)"]'
        post.hook.restore.velero.io/on-error: Continue
        post.hook.restore.velero.io/timeout: 30s
    spec:
      containers:
      - name: app
        image: busybox:1.35
        command: ["/bin/sh"]
        args:
        - -c
        - |
          echo "Starting ${APP_NAME} application..."
          echo "Pod: \$(hostname)" > /data/pod-info.txt
          echo "Started at: \$(date)" >> /data/pod-info.txt
          
          # Keep container running and simulate some work
          while true; do
            echo "\$(date): Application running on \$(hostname)" >> /data/app.log
            sleep 30
          done
        volumeMounts:$VOLUME_MOUNTS
        resources:
          requests:
            memory: "32Mi"
            cpu: "50m"
          limits:
            memory: "64Mi"
            cpu: "100m"
        livenessProbe:
          exec:
            command:
            - /bin/sh
            - -c
            - "test -f /data/pod-info.txt"
          initialDelaySeconds: 10
          periodSeconds: 30
        readinessProbe:
          exec:
            command:
            - /bin/sh
            - -c
            - "test -f /data/pod-info.txt"
          initialDelaySeconds: 5
          periodSeconds: 10
      volumes:$VOLUMES
EOF
}

# Wait for pods to be ready
wait_for_pods() {
    if [[ "$WAIT_READY" == false ]]; then
        log "Skipping wait for pod readiness"
        return 0
    fi
    
    log "Waiting for $REPLICAS pods to be ready..."
    
    # Wait up to 5 minutes
    for i in {1..30}; do
        READY_PODS=$($KUBECTL_CMD get pods -n "$NAMESPACE" -l "app=$APP_NAME" --no-headers 2>/dev/null | grep "Running" | wc -l 2>/dev/null)
        READY_PODS=${READY_PODS:-0}
        
        if [[ "$READY_PODS" -eq "$REPLICAS" ]]; then
            success "All $REPLICAS pods are ready!"
            break
        fi
        
        log "Ready pods: $READY_PODS/$REPLICAS - waiting... ($i/30)"
        sleep 10
    done
    
    # Final check
    READY_PODS=$($KUBECTL_CMD get pods -n "$NAMESPACE" -l "app=$APP_NAME" --no-headers 2>/dev/null | grep "Running" | wc -l 2>/dev/null)
    READY_PODS=${READY_PODS:-0}
    if [[ "$READY_PODS" -ne "$REPLICAS" ]]; then
        warn "Only $READY_PODS out of $REPLICAS pods are ready"
        
        if [[ $VERBOSE == true ]]; then
            log "Pod status:"
            $KUBECTL_CMD get pods -n "$NAMESPACE" -l "app=$APP_NAME"
        fi
    fi
}

# Show deployment summary
show_summary() {
    log ""
    log "=== Deployment Summary ==="
    log "Application: $APP_NAME"
    log "Namespace: $NAMESPACE"
    log "Type: $APP_TYPE"
    log "Expected Replicas: $REPLICAS"
    
    # Get actual pod count and status
    if $KUBECTL_CMD get namespace "$NAMESPACE" &> /dev/null; then
        ACTUAL_PODS=$($KUBECTL_CMD get pods -n "$NAMESPACE" -l "app=$APP_NAME" --no-headers 2>/dev/null | wc -l || echo "0")
        RUNNING_PODS=$($KUBECTL_CMD get pods -n "$NAMESPACE" -l "app=$APP_NAME" --no-headers 2>/dev/null | grep -c "Running" || echo "0")
        
        log "Actual Pods: $ACTUAL_PODS"
        log "Running Pods: $RUNNING_PODS"
        
        log ""
        log "Pods:"
        $KUBECTL_CMD get pods -n "$NAMESPACE" -l "app=$APP_NAME" 2>/dev/null || log "No pods found"
        
        if [[ "$CREATE_PVC" == true ]]; then
            log ""
            log "PVC:"
            $KUBECTL_CMD get pvc -n "$NAMESPACE" "${APP_NAME}-pvc" 2>/dev/null || log "No PVC found"
        fi
        
        log ""
        log "Services:"
        $KUBECTL_CMD get svc -n "$NAMESPACE" -l "app=$APP_NAME" 2>/dev/null || log "No services found"
        
        # Test connectivity
        if [[ "$APP_TYPE" == "nginx" && "$RUNNING_PODS" -gt 0 ]]; then
            log ""
            log "Testing nginx connectivity..."
            POD_NAME=$($KUBECTL_CMD get pods -n "$NAMESPACE" -l "app=$APP_NAME" --no-headers | head -1 | awk '{print $1}')
            if [[ -n "$POD_NAME" ]]; then
                $KUBECTL_CMD exec -n "$NAMESPACE" "$POD_NAME" -- curl -s localhost/health || warn "Health check failed"
            fi
        fi
        
    else
        error "Namespace $NAMESPACE not found"
    fi
    
    log ""
    log "=== Next Steps ==="
    log "1. Run backup script:"
    log "   ./verify_velero_backup_hooks.sh -b ${APP_NAME}-backup -a $NAMESPACE -c"
    log ""
    log "2. Run restore script:"  
    log "   ./verify_velero_restore_hooks.sh -r ${APP_NAME}-restore -b ${APP_NAME}-backup -c"
    log ""
    log "3. Clean up when done:"
    log "   $KUBECTL_CMD delete namespace $NAMESPACE"
}

# Main execution
log "Starting deployment of $APP_TYPE application..."

# Create namespace
create_namespace

# Create PVC if needed
create_pvc

# Deploy based on app type
case "$APP_TYPE" in
    "mysql")
        deploy_mysql
        ;;
    "nginx") 
        deploy_nginx
        ;;
    "generic")
        deploy_generic
        ;;
    *)
        error "Unsupported app type: $APP_TYPE"
        exit 1
        ;;
esac

success "Application $APP_NAME deployed successfully"

# Wait for pods
wait_for_pods

# Show summary
show_summary

success "Deployment completed!"
