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

AUTOEncrypt=${3:-true}
USE_CN_MIRROR=${4:-false}
IPFS=${5:-true}

upgrade=false

# Process the third argument (AUTOEncrypt)
if [ "$3" = "true" ]; then
  AUTOEncrypt=true
fi


for arg in "$@"; do
  if [ "$arg" = "-u" ]; then
    upgrade=true
    break
  fi
done


shift $((OPTIND - 1))

# ... Other script code

if [ "$upgrade" = true ]; then
  echo "Upgrade is set to true."
fi

if [ "$AUTOEncrypt" = true ]; then
  echo "AUTOEncrypt is set to true."
fi


docker_env_file_path="/etc/apt/docker_sources.env"
mpd_port_file="/data/mpd/mpdport"
# Define Docker Compose file path and services
COMPOSE_DIR="/opt/facmgr/service"
COMPOSE_FILE="$COMPOSE_DIR/docker-compose.yml"
COMPOSE_URL="./docker-compose.yml"

VAULT_URL="./vault.sh"
INIT_VAULT_CONFIG_URL="./config.hcl"
COMPOSE_FILE_AUTO_ENCRYPT="$COMPOSE_DIR/docker-compose-vault.yml"
SERVICE_FILE_URL="./facmgr_docker.service"

#CN_DOCKER_HUB_REPO="registry.cn-hangzhou.aliyuncs.com"
CN_DOCKER_HUB_REPO="maxio2-registry.cn-hangzhou.cr.aliyuncs.com"
DEFAULT_DOCKER_HUB_REPO="docker.io"
if [ "$USE_CN_MIRROR" = "true" ]; then
  DOCKER_HUB_REPO="DOCKER_HUB_REPO=$CN_DOCKER_HUB_REPO"
  COMPOSE_URL_AUTO_ENCRYPT="./docker-compose-vault_cn.yml"
  COMPOSE_URL_AUTO_ENCRYPT_TEMP="./temp/docker-compose-vault_cn.yml"
else
  DOCKER_HUB_REPO="DOCKER_HUB_REPO=$DEFAULT_DOCKER_HUB_REPO"
  COMPOSE_URL_AUTO_ENCRYPT="./docker-compose-vault.yml"
  COMPOSE_URL_AUTO_ENCRYPT_TEMP="./temp/docker-compose-vault.yml"
fi
DOCKER_HUB_REPO_LIST=("$CN_DOCKER_HUB_REPO" "$DEFAULT_DOCKER_HUB_REPO")
SERVICE_FILE_PATH="/etc/systemd/system/facmgr_docker.service"
INIT_SCRIPT_URL="./mpd.sql"
VAULT_ENV="/data/vault/config/minio_env.txt"
if [[ ! $AUTOEncrypt == true ]]; then
  SERVICES="prox_mpd pin_service minio minio-token"
else
  if [[ $IPFS == true ]]; then
    SERVICES="vault kes minio minio-token ipfs prox_mpd"
  else
    SERVICES="vault kes minio minio-token prox_mpd"
  fi
fi

if [ "$upgrade" = true ]; then
  if [[ ! $AUTOEncrypt == true ]]; then
    SERVICES="prox_mpd"
  else
    #SERVICES="vault kes minio minio-token prox_mpd pin_service"
    SERVICES="prox_mpd"
  fi
fi

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="./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"
INIT_VAULT="/data/vault/config"
INIT_DATA="/data/vault"
INIT_VAULT_CONFIG="/data/vault/config/init_vault.sh"
INIT_VAULT_CONFIG_HCL="/data/vault/config/config.hcl"
INIT_MPD_DB_FLAG="/opt/.mpddb"
IPFS_DATA="/data/ipfs/data"
IPFS_FUSE="/data/ipfs/ipfs"
IPNS="/data/ipfs/ipns"

if [[ $IPFS == true ]]; then
    DIRS=("$COMPOSE_DIR" "$INIT_VAULT" "$MINIO_DIR" "$MPD_CONF" "$MPD_LOG" "$PIN_CONFIG" "$VFS_DIR" "$BACKUP_DIR" "$IPFS_DATA" "$IPFS_FUSE" "$IPNS")
else
    DIRS=("$COMPOSE_DIR" "$INIT_VAULT" "$MINIO_DIR" "$MPD_CONF" "$MPD_LOG" "$PIN_CONFIG" "$VFS_DIR" "$BACKUP_DIR")
fi

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 ["vault"]=8200 ["kes"]=7373)
MOUNT_POINT=$(df -P "$VFS_DIR" | awk 'END{print $NF}')

if [[ ! $AUTOEncrypt == true ]]; then
        COMPOSE_FILE="$COMPOSE_FILE"
        COMPOSE_URL="$COMPOSE_URL"
else
        COMPOSE_FILE="$COMPOSE_FILE_AUTO_ENCRYPT"
        COMPOSE_URL="$COMPOSE_URL_AUTO_ENCRYPT"
fi


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

}


function update_compose_env {



  if [ -f "$docker_env_file_path" ] && [ -s "$docker_env_file_path" ]; then
    OLD_DOCKER_HUB_REPO=$(grep '^DOCKER_HUB_REPO=' "$docker_env_file_path" | cut -d'=' -f2)
    
    if [[ " ${DOCKER_HUB_REPO_LIST[@]} " =~ " ${OLD_DOCKER_HUB_REPO} " ]]; then
        log "DOCKER_HUB_REPO is in the DOCKER_HUB_REPO_LIST."
        rm "$docker_env_file_path"
    fi
  else
    log "File $docker_env_file_path does not exist or is empty."
  fi


  if [ -f "$docker_env_file_path" ] && [ -s "$docker_env_file_path" ]; then
    log "File $docker_env_file_path already exists and has content, writes are ignored."
  else
    echo "$DOCKER_HUB_REPO" > "$docker_env_file_path"
    log "Contents have been written to file $docker_env_file_path."
  fi

  if [ -f "$docker_env_file_path" ] && [ -s "$docker_env_file_path" ]; then
    NEW_DOCKER_HUB_REPO=$(grep '^DOCKER_HUB_REPO=' "$docker_env_file_path" | cut -d'=' -f2)

    if [ -n "$NEW_DOCKER_HUB_REPO" ]; then
        sed "s/\${DOCKER_HUB_REPO}/$NEW_DOCKER_HUB_REPO/g" "$COMPOSE_URL_AUTO_ENCRYPT_TEMP" > "$COMPOSE_URL_AUTO_ENCRYPT"
        log "$COMPOSE_URL_AUTO_ENCRYPT,Replacement successful: \${DOCKER_HUB_REPO} variable in docker-compose file has been replaced with specific content: $DOCKER_HUB_REPO"
    else
        log "DOCKER_HUB_REPO variable value in file $docker_env_file_path not found"
    fi
  else
    log "The file $docker_env_file_path does not exist or has empty contents."
  fi


}

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

shift $((OPTIND - 1))

if $upgrade; then
  log "Upgrade is set to true."
else
  log "Upgrade is set to false."
fi



check_parm() {
    # 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_root() {
    # Check if script is run as root
    if [[ $EUID -ne 0 ]]; then
        log "This script must be run as root"
        exit 1
    fi
}


package_install() {
    required_tools=("jq" "docker" "docker-compose" "systemctl" "nc" "sqlite3")
    for tool in "${required_tools[@]}"; do
        if dpkg-query -W -f='${Status}' "$tool" 2>/dev/null | grep -q "install ok installed"; then
            log "$tool is already installed. Skipping..."
        else
            log "$tool is missing. Adding to installation list..."
            install_commands+=("apt-get install -y $tool")
        fi
    done

    for cmd in "${install_commands[@]}"; do
        $cmd &
        done
    wait

}

create_dir() {
    # 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
}


update_compose() {
    update_compose_env
    cp "$COMPOSE_URL" "$COMPOSE_FILE"
    #if [ ! -f "$COMPOSE_FILE" ] || ! cmp -s <(cat "$COMPOSE_URL") "$COMPOSE_FILE"; then
    #    log "Docker Compose file is missing or outdated. Copying..."
    #    cp "$COMPOSE_URL" "$COMPOSE_FILE"
    #fi


}

delete_image() {
    if [ ! -f "$VAULT_ENV" ]; then
        touch "$VAULT_ENV"
        echo "File $VAULT_ENV created successfully."
    else
        echo "File $VAULT_ENV already exists. Skipping creation."
    fi

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

    # Check if Docker Compose is running
    if [[ ! $AUTOEncrypt == true ]]; then
        if [ "$(docker-compose -f $COMPOSE_FILE ps -q)" ]; then
            log "Docker Compose is running. Restarting..."
            if [ "$upgrade" = false ]; then
                docker-compose -f $COMPOSE_FILE down
            fi
            for service in "${SERVICES[@]}"; do
                docker stop "$service" 2>/dev/null || true
                docker rm "$service" 2>/dev/null || true
                docker rmi "$service" --force 2>/dev/null || true
            done
        fi
    else
        if [ "$(docker-compose -f $COMPOSE_FILE_AUTO_ENCRYPT ps -q)" ]; then
            log "Docker Compose is running. Restarting..."
            if [ "$upgrade" = false ]; then
                docker-compose -f $COMPOSE_FILE_AUTO_ENCRYPT down
                docker-compose -f $COMPOSE_FILE down
            fi
            for service in "${SERVICES[@]}"; do
                docker stop "$service" 2>/dev/null || true
                docker rm "$service" 2>/dev/null || true
                docker rmi "$service" --force 2>/dev/null || true
            done
        fi
    fi


    for service in "${SERVICES[@]}"; do
        if docker ps -aq --filter "name=$service" >/dev/null; then
            docker stop "$service" 2>/dev/null || true
            docker rm "$service" 2>/dev/null || true
            docker rmi "$service" --force 2>/dev/null || true
            echo "Container $service stopped, removed, and image deleted."
        else
            echo "Container $service does not exist."
        fi
    done


    for image in "${SERVICES[@]}"; do
        if docker images -q "$image" >/dev/null; then
            docker rmi "$image" --force 2>/dev/null || true
            echo "Image $image deleted."
        else
            echo "Image $image does not exist."
        fi
    done
}

umount_vfs(){
# Unmount directory if necessary
    if [ "$VFS_DIR" = "$MOUNT_POINT" ]; then
        log "Directory $VFS_DIR is a mount point. Unmounting..."
        umount -l "$VFS_DIR" 2>/dev/null || true
    fi
}


init_vault(){ 
    cp -r $MINIO_POLICY_URL $MINIO_POLICY

    if [[ $AUTOEncrypt == true ]]; then
        sed -i "s,{{ use_cn_mirror }},$USE_CN_MIRROR,g" $VAULT_URL
        cp -r $VAULT_URL $COMPOSE_DIR/vault.sh
        source $COMPOSE_DIR/vault.sh
        cp -r $INIT_VAULT_CONFIG_URL $INIT_VAULT_CONFIG_HCL
        chmod +x $INIT_VAULT_CONFIG
    fi
}


pull_image() {
      	
    # Get the last update time
    if [ -f $LAST_UPDATE_FILE ]; then
        LAST_UPDATE=$(cat $LAST_UPDATE_FILE)
    else
        LAST_UPDATE=0
    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..."
    if [ "$upgrade" = false ]; then
        #systemctl restart docker
        docker builder prune -f
        log "docker builder prune successful"
    fi

    if [[ ! $AUTOEncrypt == true ]]; then
        COMPOSE_HTTP_TIMEOUT=600 docker-compose -f $COMPOSE_FILE pull
        date +%s > $LAST_UPDATE_FILE
    else
        touch $VAULT_ENV
        COMPOSE_HTTP_TIMEOUT=600 docker-compose -f $COMPOSE_FILE_AUTO_ENCRYPT pull $SERVICES
        date +%s > $LAST_UPDATE_FILE
    fi

    log "docker-compose pull image"

    if [ $? -eq 124 ]; then
        log "Pull command timed out. Performing individual image pulls..."
        exit 1
        # Perform individual image pulls using docker pull
        # Replace the <service-name> with your service name
    fi
}

init_mpd_db(){

    if [ ! -f "$INIT_MPD_DB_FLAG" ]; then
        log "Database not found, initializing..."
        cp -r $INIT_SCRIPT_URL $INIT_SCRIPT
        sqlite3 "$MDP_DB" < "$INIT_SCRIPT"
        touch $INIT_MPD_DB_FLAG
    fi
}

# Check if a port is open
#is_port_open() {
#    if [[ $1 -gt 0 ]]; then
#        #nc -z localhost "$1" >/dev/null 2>&1
#        nc -z localhost "$1"
#    fi
#}


function is_port_open {
    local port=$1
    if [[ $port -gt 0 ]]; then
            netstat -anp | grep ":$port\s" | grep "LISTEN"
    fi
}

# 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"
}


env_set() {
    if [ -n "$MINIO_ACCESSKEY" ]; then
        unset MINIO_ACCESSKEY
    fi

    if [ -n "$MINIO_SECRETKEY" ]; then
        unset MINIO_SECRETKEY
    fi

    export MINIO_ACCESSKEY=$AK
    export MINIO_SECRETKEY=$SK

    sed -i '/^MINIO_ACCESSKEY=/d' ~/.bashrc
    echo "export MINIO_ACCESSKEY=$AK" >> ~/.bashrc

    sed -i '/^MINIO_SECRETKEY=/d' ~/.bashrc
    echo "export MINIO_SECRETKEY=$SK" >> ~/.bashrc

    if [ -f ~/.bashrc ]; then
        source ~/.bashrc
    fi

    #env_file="$(pwd)/.env"
}

minio_env(){

  env_file="/opt/facmgr_install/.env"
  if [ -f "$env_file" ] && grep -q "MINIO_ACCESSKEY" "$env_file" && grep -q "MINIO_SECRETKEY" "$env_file"; then
    echo "Environment variables already exist in $env_file. Skipping writing."
  else
    echo "MINIO_ACCESSKEY=$AK" > "$env_file"
    echo "MINIO_SECRETKEY=$SK" >> "$env_file"
    log "Environment variables have been written to $env_file."
  fi
  target_dir="/opt/facmgr/service"
  if [ ! -f "$target_dir/.env" ]; then
    cp "$env_file" "$target_dir/.env"
    log "Environment file copied to $target_dir/.env."
  fi
}

# Start a service and check its status

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
    MAX_RETRIES=30
    TRIES=0
    RETRY_FAILED_COUNT=0
    RETRY_INTERVAL=10
    while [ $TRIES -lt $MAX_RETRIES ]; do
        if is_port_open $PORT; then
            log "$SERVICE_NAME started and is healthy."
            break
        else
            echo "Port $PORT is not open. Retrying..."
            sleep $RETRY_INTERVAL
	    TRIES=`expr $TRIES + 1`;
	    RETRY_FAILED_COUNT=`expr $RETRY_FAILED_COUNT + 1`;
        fi
    done

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







run_service() {
    # Start services
    for SERVICE in $SERVICES; do
        start_service $SERVICE
        if [ "$SERVICE" == "ipfs" ]; then
          config_file="/data/ipfs/data/config"
          if [ -f "$config_file" ]; then
            sed -i 's/"StorageMax": "10GB"/"StorageMax": "100GB"/g' "$config_file"
            docker restart ipfs
          fi
        fi
    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..."
        cp -r  $SERVICE_FILE_URL $SERV $SERVICE_FILE_PATH
        systemctl daemon-reload
        systemctl enable facmgr_docker.service
    fi

    log "All services started successfully."
}

cron_job() {
    # 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
}


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


}




cron_start_docker() {

    # Add the cron job

    (crontab -l 2>/dev/null | grep -v "/etc/cron.d/check_docker.sh" ; 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"
COMPOSE_DIR="/opt/facmgr/service"
COMPOSE_FILE="$COMPOSE_DIR/docker-compose-vault.yml"
declare -A SERVICE_PORTS=(["prox_mpd"]=6007 ["ipfs"]=4001 ["pin_service"]=9091 ["minio"]=9000 ["minio-token"]=9000 ["vault"]=8200 ["kes"]=7373)

function is_port_open {
    local port=$1
    netstat -anp | grep -w "LISTEN" | grep -w "$port"
}


function start_service {
    local SERVICE_NAME=$1
    local PORT=${SERVICE_PORTS[$SERVICE_NAME]}

    echo "Starting $SERVICE_NAME..." >> "$log_file"
    cd $COMPOSE_DIR
    docker-compose -f $COMPOSE_FILE up -d $SERVICE_NAME

    echo "Waiting for $SERVICE_NAME to start..." >> "$log_file"
    sleep 10

    local MAX_RETRIES=30
    local TRIES=0
    while [ $TRIES -lt $MAX_RETRIES ]; do
        if is_port_open $PORT; then
            echo "$SERVICE_NAME started and is healthy." >> "$log_file"
            break
        else
            echo "Port $PORT is not open. Retrying..." >> "$log_file"
            sleep 10
            ((TRIES++))
        fi
    done

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


function prepare_service {
    local SERVICE_NAME=$1

    if [ "$SERVICE_NAME" == "kes" ]; then
        echo "Preparing $SERVICE_NAME by cleaning certificates..." >> "$log_file"
        rm -rf /data/kes/certs/*
        rm -rf /data/minio/certs/*
    elif [ "$SERVICE_NAME" == "prox_mpd" ]; then
        echo "Preparing $SERVICE_NAME by unmounting /data/vfs..." >> "$log_file"
        umount /data/vfs -l
    fi
}

function check_and_start_container {
    local SERVICE_NAME=$1

    if [ "$SERVICE_NAME" == "ipfs" ]; then
      local expected_image=$(grep "image:" $COMPOSE_FILE | grep -E "ipfs|kubo" | awk '{print $2}')
    elif [ "$SERVICE_NAME" == "minio" ]; then
      local expected_image=$(grep "image:" $COMPOSE_FILE | grep "minio" | grep -v "mc" | awk '{print $2}')
    else
      local expected_image=$(grep "image:" $COMPOSE_FILE | grep "$SERVICE_NAME" | awk '{print $2}')
    fi

    local current_image=$(docker inspect -f '{{.Config.Image}}' $SERVICE_NAME 2>/dev/null)
    local container_status=$(docker inspect -f '{{.State.Status}}' $SERVICE_NAME 2>/dev/null)
    echo "expected_image is $expected_image,current_image is $current_image,container_status is $container_status" >> "$log_file"
    if [ "$container_status" != "running" ]; then
        echo "[$(date +"%Y-%m-%d %H:%M:%S")] $SERVICE_NAME container is not running, starting it..." >> "$log_file"
        prepare_service $SERVICE_NAME
        docker stop $SERVICE_NAME >> "$log_file" 2>&1
        docker rm $SERVICE_NAME >> "$log_file" 2>&1
        start_service $SERVICE_NAME
    elif [ "$current_image" != "$expected_image" ]; then
        echo "[$(date +"%Y-%m-%d %H:%M:%S")] $SERVICE_NAME container is running with an unexpected image ($current_image), restarting it with the expected image ($expected_image)..." >> "$log_file"
        prepare_service $SERVICE_NAME
        docker stop $SERVICE_NAME >> "$log_file" 2>&1
        docker rm $SERVICE_NAME >> "$log_file" 2>&1
        start_service $SERVICE_NAME
    else
        echo "[$(date +"%Y-%m-%d %H:%M:%S")] $SERVICE_NAME container is running with the expected image ($current_image)." >> "$log_file"
    fi
}

function check_and_start_containers {
    check_and_start_container vault
    check_and_start_container kes
    check_and_start_container minio
    check_and_start_container prox_mpd
    check_and_start_container ipfs
}

svc_state=$(sqlite3 /var/lib/facmgr/db/facmgr.db "select svc_state from service;")
echo "svc service state is $svc_state" >> "$log_file"

if [ "$svc_state" = "finish" ]; then
    check_and_start_containers
fi

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
}

restart_docker() {
    systemctl restart docker
    log "Start to restart Docker"
}



generate_random_port() {
  echo $((RANDOM % (26000 - 24000 + 1) + 24000))
}

is_port_in_use() {
  local port=$1
  nc -z 127.0.0.1 $port
}

write_port_to_file() {
  local port=$1
  local file_path=$2
  echo $port > $file_path
}


main() {
  create_log
  check_parm
  check_root
  if [ "$upgrade" = false ]; then
      rm -rf $INIT_DATA
      rm -rf $INIT_MPD_DB_FLAG
      package_install
      umount_vfs

      directories=(ipfs kes minio vault)

      for dir in "${directories[@]}"; do
        dir_path="${DataDIR}/${dir}"
        if [ -d "$dir_path" ]; then
            rm -rf "$dir_path"
            log "Deleted directory: $dir_path"
        else
            log "Directory does not exist: $dir_path"
        fi
      done
      log "Deleted $DataDIR."

      create_dir
  fi
  update_compose
  if [ "$upgrade" = false ]; then
      env_set
      src_dir="/opt/facmgr_install"
      dst_mpd_dir="/data/mpd/config"
      dst_pin_service_dir="/data/pin_service"

      if [ ! -f "$dst_mpd_dir/config.json" ] && [ -f "$src_dir/config.json" ]; then
        cp "$src_dir/config.json" "$dst_mpd_dir/"
        echo "Copied config.json to $dst_mpd_dir"
      fi

      if [ ! -f "$dst_pin_service_dir/config.toml" ] && [ -f "$src_dir/config.toml" ]; then
        cp "$src_dir/config.toml" "$dst_pin_service_dir/"
        echo "Copied config.toml to $dst_pin_service_dir"
      fi

      local random_port=$(generate_random_port)

      while is_port_in_use $random_port; do
        random_port=$(generate_random_port)
      done
      write_port_to_file $random_port $mpd_port_file
      echo "Random port $random_port generated and written to $mpd_port_file"
      sed -i "s,24000,$random_port,g" $COMPOSE_FILE_AUTO_ENCRYPT
      sed -i "s,24000,$random_port,g" $COMPOSE_URL_AUTO_ENCRYPT

  fi
  if [ "$upgrade" = true ]; then
      create_dir
      #restart_docker
      umount_vfs

      [ -f /etc/cron.d/check_docker.sh ] && rm /etc/cron.d/check_docker.sh

      cron_jobs=("check_docker.sh")

      for job in "${cron_jobs[@]}"; do
        if crontab -l | grep -q "$job"; then
          rm -f "/etc/cron.d/$job"
        fi
      done

      systemctl restart cron



      if [ -s "$mpd_port_file" ]; then
          port=$(cat "$mpd_port_file")
          sed -i "s,24000,$port,g" $COMPOSE_FILE_AUTO_ENCRYPT
          sed -i "s,24000,$port,g" $COMPOSE_URL_AUTO_ENCRYPT
      else
          local random_port=$(generate_random_port)
          while is_port_in_use $random_port; do
              random_port=$(generate_random_port)
          done
          write_port_to_file $random_port $mpd_port_file
          sed -i "s,24000,$random_port,g" $COMPOSE_FILE_AUTO_ENCRYPT
          sed -i "s,24000,$random_port,g" $COMPOSE_URL_AUTO_ENCRYPT
      fi

  fi

 
  minio_env
  init_vault
  delete_image
  pull_image
  init_mpd_db
  run_service
  cron_job
  add_cyfs_toml
  cron_start_docker
}
main


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