#!/bin/bash
set -e
AK=$1
SK=$2



# Define Docker Compose file path and services
COMPOSE_DIR="/opt/facmgr/service"
COMPOSE_FILE="$COMPOSE_DIR/docker-compose.yml"
COMPOSE_URL="http://dl.fogworks.io/facmgr/docker-compose.yml"
SERVICE_FILE_URL="http://dl.fogworks.io/facmgr/facmgr_docker.service"
SERVICE_FILE_PATH="/etc/systemd/system/facmgr_docker.service"
INIT_SCRIPT_URL="http://dl.fogworks.io/facmgr/mpd.sql"
SERVICES="prox_mpd pin_service minio minio-token"
LOG_DIR="/var/log/facmgr"
LOG_FILE="$LOG_DIR/docker-compose.log"
DataDIR="/data"
VFS_DIR="$DataDIR/vfs"
MINIO_DIR="$DataDIR/minio"
MINIO_POLICY="/opt/.policy.json"
MINIO_POLICY_URL="http://dl.fogworks.io/facmgr/policy.json"
MPD_CONF="$DataDIR/mpd/config"
MDP_DB="$DataDIR/mpd/meta.db"
INIT_SCRIPT="$DataDIR/mpd/mpd.sql"
MPD_LOG="$DataDIR/mpd/log"
PIN_CONFIG="$DataDIR/pin_service/config"
BACKUP_DIR="$DataDIR/mpd/backup"

DIRS=("$COMPOSE_DIR" "$MINIO_DIR" "$MPD_CONF" "$MPD_LOG" "$PIN_CONFIG" "$VFS_DIR" "$BACKUP_DIR")
LAST_UPDATE_FILE="/opt/facmgr/last_update.txt"
# Define the port number for each service. Update this according to your services.
declare -A SERVICE_PORTS=(["prox_mpd"]=6007 ["pin_service"]=9091 ["minio"]=9000 ["minio-token"]=9000)

if [ ! -d "$LOG_DIR" ]; then
  echo "Directory $DIR does not exist. Creating..."
  mkdir -p "$LOG_DIR"
fi

function log {
    echo "$(date +"%Y-%m-%d %H:%M:%S") - $1" | tee -a $LOG_FILE
}

# Check if AK and SK are set
if [ -z "$AK" ] || [ -z "$SK" ]; then
    log "AK and/or SK are not set. Please provide them as arguments."
    exit 1
fi


# Check if script is run as root
if [[ $EUID -ne 0 ]]; then
   log "This script must be run as root"
   exit 1
fi


umount /data/vfs 2>/dev/null || true


apt-get update
# Check if required tools are installed, if not, install them
required_tools=("curl" "docker" "docker-compose" "wget" "systemctl" "nc" "sqlite3")
for tool in "${required_tools[@]}"; do
    if ! command -v $tool &>/dev/null; then
       log "$tool is missing. Installing $tool..."

       apt-get install -y $tool
    fi
done

# Create necessary directories if they don't exist
for DIR in "${DIRS[@]}"; do
  if [ ! -d "$DIR" ]; then
    log "Directory $DIR does not exist. Creating..."
    mkdir -p "$DIR"
  fi
done

MOUNT_POINT=$(df -P "$VFS_DIR" | awk 'END{print $NF}')

# Check if Docker Compose file is up-to-date
if ! [ -f $COMPOSE_FILE ]; then
   log "Docker Compose file is missing. Downloading..."
   curl -s $COMPOSE_URL -o $COMPOSE_FILE
elif [ "$(curl -s $COMPOSE_URL | md5sum)" = "$(md5sum $COMPOSE_FILE)" ]; then
   log "Docker Compose file is outdated. Updating..."
   curl -s $COMPOSE_URL -o $COMPOSE_FILE
fi


# Check if Docker is running
if ! systemctl is-active --quiet docker; then
  log "Docker is not running. Starting Docker..."
  systemctl start docker
fi

# Check if Docker Compose is running
if [ "$(docker-compose -f $COMPOSE_FILE ps -q)" ]; then
  log "Docker Compose is running. Restarting..."
  docker-compose -f $COMPOSE_FILE down
fi

# Unmount directory if necessary
if [ "$VFS_DIR" = "$MOUNT_POINT" ]; then
  log "Directory $VFS_DIR is a mount point. Unmounting..."
  umount -l "$VFS_DIR"
fi

# Ensure VFS_DIR exists
if [ ! -d "$VFS_DIR" ]; then
    log "Directory $VFS_DIR does not exist. Creating..."
    mkdir -p "$VFS_DIR"
fi

# Get the last update time
if [ -f $LAST_UPDATE_FILE ]; then
    LAST_UPDATE=$(cat $LAST_UPDATE_FILE)
else
    LAST_UPDATE=0
fi



wget $MINIO_POLICY_URL -O $MINIO_POLICY

# Update Docker images if necessary
#if [ $(( $(date +%s) - $LAST_UPDATE )) -gt $((7*24*60*60)) ]; then
#  log "More than a week has passed since the last update. Checking for updates..."
#  docker-compose -f $COMPOSE_FILE pull
#  date +%s > $LAST_UPDATE_FILE
#fi


export DOCKER_CLIENT_TIMEOUT=600
export COMPOSE_HTTP_TIMEOUT=600
log "More than a week has passed since the last update. Checking for updates..."
docker builder prune -f 
log "docker builder prune successful"
COMPOSE_HTTP_TIMEOUT=600 docker-compose -f $COMPOSE_FILE pull
log "docker-compose pull image"

if [ $? -eq 124 ]; then
  log "Pull command timed out. Performing individual image pulls..."

  # Perform individual image pulls using docker pull
  # Replace the <service-name> with your service name
  docker pull vofo/prox_mpd:rc2
  docker pull vofo/pin_service:rc2
  docker pull minio/minio 
  docker pull minio/mc
fi

date +%s > $LAST_UPDATE_FILE


if [ ! -f "$MDP_DB" ]; then
    echo "Database not found, initializing..."
    wget $INIT_SCRIPT_URL -O $INIT_SCRIPT
    sqlite3 "$MDP_DB" < "$INIT_SCRIPT"
fi


# Check if a port is open
function is_port_open {
    nc -z localhost $1
}

# Check if a service is healthy
function is_service_healthy {
    docker inspect --format "{{json .State.Health.Status }}" $1
    docker inspect --format "{{json .State.Health.Status }}" $1 | grep -q "healthy"
}

export MINIO_ACCESSKEY=$AK
export MINIO_SECRETKEY=$SK

if ! grep -qxF "MINIO_ACCESSKEY=$AK" ~/.bashrc ; then
    echo "export MINIO_ACCESSKEY=$AK" >> ~/.bashrc
fi


if ! grep -qxF "MINIO_SECRETKEY=$SK" ~/.bashrc ; then
    echo "export MINIO_SECRETKEY=$SK" >> ~/.bashrc
fi


function add_cyfs_toml {

if [ ! -d "/cyfs/etc/app-manager" ]; then
    mkdir -p "/cyfs/etc/app-manager"
fi

cat > "/cyfs/etc/app-manager/app-manager.toml" <<EOF
[config]
sandbox = "default"

[app]
source = "user"
EOF


}
# Start a service and check its status
function start_service {
    SERVICE_NAME=$1
    PORT=${SERVICE_PORTS[$SERVICE_NAME]}

    log "Starting $SERVICE_NAME..."
    docker-compose -f $COMPOSE_FILE up -d $SERVICE_NAME

    log "Waiting for $SERVICE_NAME to start..."
    sleep 10

    # Check port status with retries
    TRIES=0
    until is_port_open $PORT || [ $TRIES -eq 5 ]; do
        log "Port $PORT is not open. Retrying..."
        sleep 2
        ((TRIES++))
    done

    if [ $TRIES -eq 5 ]; then
        log "Port $PORT is still not open after $TRIES attempts. Check the log file for details."
        exit 1
    fi

    # Get the container ID of the service
    #CONTAINER_ID=$(docker-compose -f $COMPOSE_FILE ps -q $SERVICE_NAME)

    # Check service health status with retries
    #TRIES=0
    #until is_service_healthy $CONTAINER_ID || [ $TRIES -eq 5 ]; do
    #    log "$SERVICE_NAME is not healthy. Retrying..."
    #    sleep 2
    #    ((TRIES++))
    #done

    #if [ $TRIES -eq 5 ]; then
    #    log "$SERVICE_NAME is still not healthy after $TRIES attempts. Check the log file for details."
    #    exit 1
    #fi

    log "$SERVICE_NAME started and is healthy."
}

# Start services
for SERVICE in $SERVICES; do
   start_service $SERVICE
done

# Check if the systemctl service exists
if ! systemctl list-units --full --all | grep -Fq "facmgr_docker.service"; then
   log "facmgr_docker.service does not exist. Downloading..."
   wget $SERVICE_FILE_URL -O $SERV $SERVICE_FILE_PATH
   systemctl daemon-reload
   systemctl enable facmgr_docker.service
fi


cron_start_docker(){

# Add the cron job
(crontab -l 2>/dev/null; echo "* * * * * /etc/cron.d/check_docker.sh") | crontab -

# Create the script file and write the content
script_file="/etc/cron.d/check_docker.sh"
cat << 'EOF' > "$script_file"
#!/bin/bash

log_file="/var/log/start_docker.log"

# Check container status and start them
check_and_start_containers() {
    # Check minio container status
    minio_status=$(docker inspect -f '{{.State.Status}}' minio 2>/dev/null)
    if [ "$minio_status" != "running" ]; then
        echo "[$(date +"%Y-%m-%d %H:%M:%S")] minio container is not running, starting it..." >> "$log_file"
        docker start minio >> "$log_file" 2>&1
    fi

    # Check pin_service container status
    if [ ! -f "/opt/facmgr/.pin_service" ]; then
        # .pin_service file doesn't exist, start pin_service container
        pin_service_status=$(docker inspect -f '{{.State.Status}}' pin_service 2>/dev/null)
        if [ "$pin_service_status" != "running" ]; then
            echo "[$(date +"%Y-%m-%d %H:%M:%S")] pin_service container is not running, starting it..." >> "$log_file"
            docker start pin_service >> "$log_file" 2>&1
        fi
    else
        echo "[$(date +"%Y-%m-%d %H:%M:%S")] .pin_service file exists, skipping pin_service container start." >> "$log_file"
    fi


    # Check prox_mpd container status
    prox_mpd_status=$(docker inspect -f '{{.State.Status}}' prox_mpd 2>/dev/null)
    if [ "$prox_mpd_status" != "running" ]; then
        echo "[$(date +"%Y-%m-%d %H:%M:%S")] prox_mpd container is not running, starting it..." >> "$log_file"
        umount /data/vfs -l
	docker start prox_mpd >> "$log_file" 2>&1
    fi
}

# Check and start container status, and log the actions
check_and_start_containers

echo "[$(date +"%Y-%m-%d %H:%M:%S")] Container check and start script executed" >> "$log_file"
EOF

# Make the script executable
chmod +x "$script_file"
systemctl restart cron.service
log "Cron job has been added, and the script file $script_file has been created."

}

log "All services started successfully."


# Define cron jobs
BACKUP_JOB_IDENTIFIER="# FACMGR_DB_BACKUP_JOB"
CRON_JOB_BACKUP="$BACKUP_JOB_IDENTIFIER\n0 1 * * * /usr/bin/env sqlite3 $MDP_DB '.backup '$BACKUP_DIR/db_backup_'\$(date +\%Y\%m\%d\%H\%M)'.sqlite'"

CLEANUP_JOB_IDENTIFIER="# FACMGR_DB_CLEANUP_JOB"
CRON_JOB_CLEANUP="$CLEANUP_JOB_IDENTIFIER\n0 2 * * * /usr/bin/env find $BACKUP_DIR -name 'db_backup_*.sqlite' -mtime +30 -delete"

# Add the backup cron job if it does not exist
if ! crontab -l | grep -q "$BACKUP_JOB_IDENTIFIER"; then
  (crontab -l 2>/dev/null; echo -e "$CRON_JOB_BACKUP") | crontab -
fi

# Add the cleanup cron job if it does not exist
if ! crontab -l | grep -q "$CLEANUP_JOB_IDENTIFIER"; then
  (crontab -l 2>/dev/null; echo -e "$CRON_JOB_CLEANUP") | crontab -
fi

add_cyfs_toml
cron_start_docker

log "Cron jobs for database backup and cleanup are created."
