#!/bin/bash

# URLs for configuration files
DOCKER_COMPOSE_URL="https://git.masscivicdynamic.com/masscivicdynamic/nexo-cloud-scripts/raw/branch/main/docker-compose.yml"
KUBERNETES_DEPLOY_URL="https://git.masscivicdynamic.com/masscivicdynamic/nexo-cloud-scripts/raw/branch/main/kube-deploy.yaml"
ENV_FILE="/data/nexo-cloud/.env"
DATA_DIR="/data/nexo-cloud"
SSL_DIR="$DATA_DIR/ssh"
KUBE_DIR="$DATA_DIR/kubernetes"
SSL_CERT="$SSL_DIR/server.crt"
SSL_KEY="$SSL_DIR/server.key"
KUBECONFIG_FILE="$KUBE_DIR/config"

# Minimum disk space requirements (in GB)
MIN_TOTAL_DISK_SPACE=30
MIN_AVAILABLE_DISK_SPACE=20

# Function to check if a command exists
command_exists() {
    command -v "$1" >/dev/null 2>&1
}

# Function to generate a random password
generate_random_password() {
    echo "$(openssl rand -base64 16)"
}

# Function to generate an APP_KEY
generate_app_key() {
    echo "$(openssl rand -base64 32)"
}

# Function to generate SSL certificate
generate_ssl_certificate() {
    if [ ! -f "$SSL_CERT" ] || [ ! -f "$SSL_KEY" ]; then
        echo "Generating SSL certificate..."
        mkdir -p "$SSL_DIR"
        openssl req -newkey rsa:2048 -nodes -keyout "$SSL_KEY" \
            -x509 -days 365 -out "$SSL_CERT" -subj "/CN=NexoCloud"
        echo "SSL certificate generated and stored in $SSL_DIR."
    else
        echo "SSL certificate already exists in $SSL_DIR."
    fi
}

# Function to check disk space
check_disk_space() {
    local total_space=$(df --output=size "$DATA_DIR" | tail -n 1 | awk '{print $1}')
    local available_space=$(df --output=avail "$DATA_DIR" | tail -n 1 | awk '{print $1}')
    local total_space_gb=$((total_space / 1024 / 1024))
    local available_space_gb=$((available_space / 1024 / 1024))

    if [ "$total_space_gb" -lt "$MIN_TOTAL_DISK_SPACE" ]; then
        echo "Error: Total disk space is less than $MIN_TOTAL_DISK_SPACE GB."
        exit 1
    fi

    if [ "$available_space_gb" -lt "$MIN_AVAILABLE_DISK_SPACE" ]; then
        echo "Error: Available disk space is less than $MIN_AVAILABLE_DISK_SPACE GB."
        exit 1
    fi
}

# Function to create the data directory and subdirectories if they don't exist
ensure_data_directory() {
    if [ ! -d "$DATA_DIR" ]; then
        echo "Creating data directory at $DATA_DIR..."
        mkdir -p "$DATA_DIR"
    fi

    # Create subdirectories
    for subdir in logs ssh applications databases services backups kubernetes; do
        if [ ! -d "$DATA_DIR/$subdir" ]; then
            echo "Creating subdirectory $subdir in $DATA_DIR..."
            mkdir -p "$DATA_DIR/$subdir"
        fi
    done
    echo "Directories created successfully."
}

# Function to copy kubeconfig file if Kubernetes is installed
copy_kubeconfig_file() {
    if command_exists kubectl; then
        echo "Kubernetes detected. Checking kubeconfig..."
        if [ -f "$HOME/.kube/config" ]; then
            mkdir -p "$KUBE_DIR"
            cp "$HOME/.kube/config" "$KUBECONFIG_FILE"
            echo "Kubeconfig file copied to $KUBECONFIG_FILE."
        else
            echo "Kubeconfig file not found in $HOME/.kube/config."
        fi
    elif command_exists k3s; then
        echo "K3s detected. Checking kubeconfig..."
        if [ -f "/etc/rancher/k3s/k3s.yaml" ]; then
            mkdir -p "$KUBE_DIR"
            cp "/etc/rancher/k3s/k3s.yaml" "$KUBECONFIG_FILE"
            echo "Kubeconfig file copied to $KUBECONFIG_FILE."
        else
            echo "K3s kubeconfig file not found in /etc/rancher/k3s/k3s.yaml."
        fi
    else
        echo "No Kubernetes or K3s installation detected. Skipping kubeconfig copy."
    fi
}

# Function to handle the .env file
handle_env_file() {
    if [ ! -f "$ENV_FILE" ]; then
        echo "Environment file not found. Creating a new one."
        touch "$ENV_FILE"
    fi

    APP_KEY=$(generate_app_key)
    DB_USERNAME="nexo-cloud"
    DB_PASSWORD=$(generate_random_password)
    REDIS_PASSWORD=$(generate_random_password)

    # Ask if user wants to change APP_NAME
    read -p "Do you want to change the APP_NAME? (y/n) [default: NexoCloud]: " change_app_name
    if [ "$change_app_name" == "y" ] || [ "$change_app_name" == "Y" ]; then
        read -p "Enter the new APP_NAME: " new_app_name
        APP_NAME="$new_app_name"
    else
        APP_NAME="NexoCloud"
    fi

    # Update environment variables
    sed -i '/^APP_NAME=/d' "$ENV_FILE"
    echo "APP_NAME=$APP_NAME" >> "$ENV_FILE"

    if grep -q "^APP_KEY=" "$ENV_FILE"; then
        PREVIOUS_KEYS=$(grep "^APP_PREVIOUS_KEYS=" "$ENV_FILE" | cut -d'=' -f2)
        NEW_PREVIOUS_KEYS="${PREVIOUS_KEYS},$(grep "^APP_KEY=" "$ENV_FILE" | cut -d'=' -f2)"
        sed -i '/^APP_PREVIOUS_KEYS=/d' "$ENV_FILE"
        echo "APP_PREVIOUS_KEYS=$NEW_PREVIOUS_KEYS" >> "$ENV_FILE"
    else
        echo "APP_PREVIOUS_KEYS=$APP_KEY" >> "$ENV_FILE"
    fi
    sed -i '/^APP_KEY=/d' "$ENV_FILE"
    echo "APP_KEY=$APP_KEY" >> "$ENV_FILE"

    if ! grep -q "^DB_USERNAME=" "$ENV_FILE"; then
        echo "DB_USERNAME=$DB_USERNAME" >> "$ENV_FILE"
    fi

    if ! grep -q "^DB_PASSWORD=" "$ENV_FILE"; then
        echo "DB_PASSWORD=$DB_PASSWORD" >> "$ENV_FILE"
    fi

    if ! grep -q "^REDIS_PASSWORD=" "$ENV_FILE"; then
        echo "REDIS_PASSWORD=$REDIS_PASSWORD" >> "$ENV_FILE"
    fi

    echo "Environment variables configured in $ENV_FILE."
}

# Function to set up Docker
setup_docker() {
    docker swarm init
    curl -o "$DATA_DIR/docker-compose.yml" "$DOCKER_COMPOSE_URL"
    docker-compose -f "$DATA_DIR/docker-compose.yml" up -d
}

# Function to deploy Kubernetes application
deploy_kubernetes() {
    curl -o "$DATA_DIR/kubernetes/kube-deploy.yaml" "$KUBERNETES_DEPLOY_URL"
    kubectl apply -f "$DATA_DIR/kubernetes/kube-deploy.yaml"
}

# Main deployment logic
deploy_application() {
    echo "Deploying the application..."
    if [ "$1" == "docker" ]; then
        setup_docker
    elif [ "$1" == "kubernetes" ]; then
        deploy_kubernetes
    fi
    echo "Deployment completed."
}

# Function to handle installation or restart
install_application() {
    echo "Do you want to:"
    echo "1) Install a fresh application"
    echo "2) Restart the deployment"
    read -p "Enter your choice (1-2): " deployment_choice

    if [ "$deployment_choice" == "1" ]; then
        ensure_data_directory
        check_disk_space
        handle_env_file
        generate_ssl_certificate

        echo "Choose the platform to install or manage:"
        echo "1) Docker"
        echo "2) Kubernetes (K8s)"
        echo "3) K3s (Lightweight Kubernetes)"
        read -p "Enter your choice (1-3): " platform_choice

        case $platform_choice in
            1)
                PLATFORM="docker"
                if ! command_exists docker; then
                    echo "Installing Docker..."
                    curl -s https://get.docker.com | sh -s --
                fi
                ;;
            2)
                PLATFORM="kubernetes"
                if ! command_exists kubectl; then
                    echo "Installing Kubernetes..."
                    apt-get update && apt-get install -y kubeadm kubectl kubelet
                fi
                copy_kubeconfig_file
                ;;
            3)
                PLATFORM="kubernetes"
                if ! command_exists k3s; then
                    echo "Installing K3s..."
                    curl -sfL https://get.k3s.io | sh -
                fi
                copy_kubeconfig_file
                ;;
            *)
                echo "Invalid choice. Exiting."
                exit 1
                ;;
        esac
        deploy_application "$PLATFORM"
    elif [ "$deployment_choice" == "2" ]; then
        echo "Restarting deployment..."
        deploy_application "$PLATFORM"
    else
        echo "Invalid choice. Exiting."
        exit 1
    fi
}

install_application