#!/usr/bin/with-contenv bash
# shellcheck shell=bash

echo "[cwa-init] Starting CWA initialization process..."

# Check for unsupported architecture
ARCH=$(uname -m)
if [[ "$ARCH" != "x86_64" && "$ARCH" != "aarch64" ]]; then
  echo "[cwa-init] WARNING: Unsupported architecture detected: $ARCH"
  echo "[cwa-init] CWA is optimized for x86_64 and aarch64. You may experience issues."
fi

# Verify essential directories exist and are accessible
echo "[cwa-init] Verifying essential directories..."
for dir in "/app/calibre-web-automated" "/config" "/calibre-library" "/app/calibre"; do
  if [[ ! -d "$dir" ]]; then
    echo "[cwa-init] ERROR: Essential directory $dir does not exist!"
    exit 1
  fi
  if [[ ! -r "$dir" ]]; then
    echo "[cwa-init] ERROR: Essential directory $dir is not readable!"
    exit 1
  fi
  echo "[cwa-init] Directory $dir verified"
done

# Verify essential files exist
echo "[cwa-init] Verifying essential files..."
for file in "/app/CWA_RELEASE" "/CALIBRE_RELEASE"; do
  if [[ ! -f "$file" ]]; then
    echo "[cwa-init] WARNING: Expected file $file does not exist"
  else
    echo "[cwa-init] File $file verified"
  fi
done

echo "[cwa-init] Environment verification complete"

# FROM lscio/docker-calibre-web - init-calibre-web-config.sh
# create symlinks for imagemagick policy.xml
echo "[cwa-init] Setting up ImageMagick policy..."
rm -rf /etc/ImageMagick-6/policy.xml
ln -s /defaults/policy.xml /etc/ImageMagick-6/policy.xml

# create Google drive client_secrets.json file
if [[ ! -f /config/client_secrets.json ]]; then
    echo "{}" > /config/client_secrets.json
fi

# check if kepubify is present and if so make executable
if [[ -f /usr/bin/kepubify ]] && [[ ! -x /usr/bin/kepubify ]]; then
    chmod +x /usr/bin/kepubify
fi

# Pre-stage some files & directories for permissions purposes
mkdir -p /app/calibre-web-automated/cps/cache

# permissions (skip chown on network shares)
if [ "${NETWORK_SHARE_MODE,,}" = "true" ] || [ "${NETWORK_SHARE_MODE}" = "1" ] || [ "${NETWORK_SHARE_MODE,,}" = "yes" ] || [ "${NETWORK_SHARE_MODE,,}" = "on" ]; then
  echo "[cwa-init] NETWORK_SHARE_MODE=true detected; skipping initial chown of /config and cps/cache"
else
  chown -R abc:abc \
    /config \
    /app/calibre-web-automated/cps/cache
fi

export CALIBRE_DBPATH=/config

if [[ ! -f /config/app.db ]]; then
  echo "First time run, creating app.db..."
  cd /app/calibre-web-automated && s6-setuidgid abc python3 /app/calibre-web-automated/cps.py -d > /dev/null 2>&1
  # handle app.db updates for kepubify and ext binary path
  # borrowed from crocodilestick because it's a better solution than what i was doing
  sqlite3 /config/app.db <<EOS
    update settings set config_kepubifypath='/usr/bin/kepubify' where config_kepubifypath is NULL or LENGTH(config_kepubifypath)=0;
EOS

  if [[ $? == 0 ]]; then
    echo "Successfully set kepubify paths in '/config/app.db'!"
  elif [[ $? > 0 ]]; then
    echo "Could not set binary paths for '/config/app.db' (see errors above)."
  fi
fi

#------------------------------------------------------------------------------------------------------------------------
#  Make sure required directories exist
#------------------------------------------------------------------------------------------------------------------------

install -d -o abc -g abc /config/processed_books/converted
install -d -o abc -g abc /config/processed_books/imported
install -d -o abc -g abc /config/processed_books/failed
install -d -o abc -g abc /config/processed_books/fixed_originals
install -d -o abc -g abc /config/processed_books/duplicate_resolutions
install -d -o abc -g abc /config/log_archive
install -d -o abc -g abc /config/.cwa_conversion_tmp

# For Calibre Plugins
install -d -o abc -g abc /config/.config/calibre/plugins
# ln -sf /config/.config/calibre/plugins /config/calibre_plugins

#------------------------------------------------------------------------------------------------------------------------
#  Remove any leftover lock files
#------------------------------------------------------------------------------------------------------------------------

declare -a lockFiles=("ingest_processor.lock" "convert_library.lock" "cover_enforcer.lock" "kindle_epub_fixer.lock")

echo "[cwa-init] Checking for leftover lock files from previous instance..."

counter=0

for f in "${lockFiles[@]}"
do
    if [ -f "/tmp/$f" ]
    then
        echo "[cwa-init] Leftover $f exists, removing now..."
        rm "/tmp/$f"
        echo "[cwa-init] Leftover $f removed."
        let counter++
    fi
done

if [[ "$counter" -eq 0 ]]
then
    echo "[cwa-init] No leftover lock files to remove. Ending service..."
else
    echo "[cwa-init] $counter lock file(s) removed. Ending service..."
fi

#------------------------------------------------------------------------------------------------------------------------
#  Check for existing app.db and create one from the included example if one doesn't already exist
#------------------------------------------------------------------------------------------------------------------------

echo "[cwa-init] Checking for an existing app.db in /config..."

if [ ! -f /config/app.db ]; then
    echo "[cwa-init] No existing app.db found! Creating new one..."
    cp /app/calibre-web-automated/empty_library/app.db /config/app.db
else
    echo "[cwa-init] Existing app.db found!"
fi

#------------------------------------------------------------------------------------------------------------------------
#  Ensure correct binary paths in app.db
#------------------------------------------------------------------------------------------------------------------------

echo "[cwa-init] Setting binary paths in '/config/app.db' to the correct ones..."

sqlite3 /config/app.db <<EOS
    update settings set config_kepubifypath='/usr/bin/kepubify', config_converterpath='/usr/bin/ebook-convert', config_binariesdir='/usr/bin';
EOS

if [[ $? == 0 ]]
then
    echo "[cwa-init] Successfully set binary paths in '/config/app.db'!"
elif [[ $? > 0 ]]
then
    echo "[cwa-init] Service could not successfully set binary paths for '/config/app.db' (see errors above)."
fi


echo "[cwa-init] CWA-init complete! Service exiting now..."

#------------------------------------------------------------------------------------------------------------------------
#  Create blank json file for profile pictures if one doesn't exist
#------------------------------------------------------------------------------------------------------------------------

if [ ! -f /config/user_profiles.json ]; then
    echo "[cwa-init] No existing user_profiles.json found! Creating blank one..."
    echo -e "{\n}" > /config/user_profiles.json
else
    echo "[cwa-init] Existing user_profiles.json found!"
fi

#------------------------------------------------------------------------------------------------------------------------
#  Set required permissions
#------------------------------------------------------------------------------------------------------------------------

declare -a requiredDirs=("/config" "/calibre-library" "/app/calibre-web-automated")

dirs=$(printf ", %s" "${requiredDirs[@]}")
dirs=${dirs:1}

echo "[cwa-init] Preparing to set ownership of everything in$dirs to abc:abc..."

for d in "${requiredDirs[@]}"; do
  if [ "${NETWORK_SHARE_MODE,,}" = "true" ] || [ "${NETWORK_SHARE_MODE}" = "1" ] || [ "${NETWORK_SHARE_MODE,,}" = "yes" ] || [ "${NETWORK_SHARE_MODE,,}" = "on" ]; then
    echo "[cwa-init] NETWORK_SHARE_MODE=true detected; skipping chown of $d"
    continue
  fi
  chown -R abc:abc "$d"
  if [[ $? == 0 ]]; then
    echo "[cwa-init] Successfully set permissions for '$d'!"
  elif [[ $? > 0 ]]; then
    echo "[cwa-init] Service could not successfully set permissions for '$d' (see errors above)."
  fi
done

#------------------------------------------------------------------------------------------------------------------------
#  Qt6 / Kernel compatibility check (conditional ABI tag stripping)
#------------------------------------------------------------------------------------------------------------------------

MIN_KERNEL="6.0"
HOST_KERNEL_RAW="$(uname -r)"
HOST_KERNEL="${HOST_KERNEL_RAW%%-*}"

version_ge() { [ "$(printf '%s\n' "$2" "$1" | sort -V | tail -n1)" = "$1" ]; }

QT_SENTINEL="/app/calibre/.qt6_processed"
if [ ! -f "$QT_SENTINEL" ]; then
  echo "[cwa-init][qt6] Starting Qt6 compatibility check..."

  if version_ge "$HOST_KERNEL" "$MIN_KERNEL"; then
    echo "[cwa-init][qt6] Host kernel $HOST_KERNEL_RAW >= $MIN_KERNEL: leaving Qt6 libs intact for full functionality." \
         "(PDF/WebEngine features enabled)"
  else
    echo "[cwa-init][qt6] Host kernel $HOST_KERNEL_RAW < $MIN_KERNEL: attempting legacy compatibility by stripping .note.ABI-tag." \
         "(This does NOT guarantee full functionality.)"

    # Add timeout protection and better error handling
    if command -v strip >/dev/null 2>&1; then
      echo "[cwa-init][qt6] Starting ABI tag removal process..."
      any_stripped=0
      processed_count=0
      error_count=0

      # Set a reasonable timeout for the entire operation
      qt6_output=$(timeout 60 bash -c '
        any_stripped=0
        processed_count=0
        error_count=0

        for f in /app/calibre/lib/libQt6*.so*; do
          [ -f "$f" ] || continue
          echo "[cwa-init][qt6] Processing: $(basename "$f")"
          processed_count=$((processed_count + 1))

          # Check if file is readable and not corrupted
          if ! file "$f" >/dev/null 2>&1; then
            echo "[cwa-init][qt6] WARNING: File $f appears corrupted, skipping"
            error_count=$((error_count + 1))
            continue
          fi

          # Use timeout for individual file operations
          if timeout 10 readelf -S "$f" 2>/dev/null | grep -q ".note.ABI-tag"; then
            echo "[cwa-init][qt6] Stripping ABI tag from $(basename "$f")"
            if timeout 10 strip --remove-section=.note.ABI-tag "$f" 2>/dev/null; then
              any_stripped=1
              echo "[cwa-init][qt6] Successfully processed $(basename "$f")"
            else
              echo "[cwa-init][qt6] WARNING: Failed to strip ABI tag from $(basename "$f")"
              error_count=$((error_count + 1))
            fi
          else
            echo "[cwa-init][qt6] No ABI tag found in $(basename "$f")"
          fi
        done

        echo "[cwa-init][qt6] Processing complete: $processed_count files processed, $error_count errors"
        [ $any_stripped -eq 1 ] && echo "STRIPPED" || echo "NO_STRIP"
      ' 2>&1) && qt6_result=$? || qt6_result=$?

      # Output the processing logs
      echo "$qt6_output"

      if [ $qt6_result -eq 124 ]; then
        echo "[cwa-init][qt6] WARNING: Qt6 processing timed out after 60 seconds. Continuing startup..."
      elif [ $qt6_result -ne 0 ]; then
        echo "[cwa-init][qt6] WARNING: Qt6 processing encountered errors. Continuing startup..."
      else
        if echo "$qt6_output" | grep -q "STRIPPED"; then
          echo "[cwa-init][qt6] ************************************* ATTENTION *************************************"
          echo "[cwa-init][qt6] Stripped ABI note from some Qt6 libs. Features may still be limited on very old kernels."
          echo "[cwa-init][qt6] This will enable devices with kernels >= $MIN_KERNEL to run CWA however features that"
          echo "[cwa-init][qt6] require Qt6 may not work as expected (e.g. working with PDF files)."
        else
          echo "[cwa-init][qt6] No ABI note sections found to strip (nothing changed)."
        fi
      fi
    else
      echo "[cwa-init][qt6] 'strip' tool not available; cannot attempt ABI tag removal."
    fi
  fi

  # Always create sentinel file to prevent re-processing
  if touch "$QT_SENTINEL" 2>/dev/null; then
    echo "[cwa-init][qt6] Qt6 compatibility check completed."
  else
    echo "[cwa-init][qt6] WARNING: Could not create sentinel file, Qt6 check may repeat on next startup."
  fi
else
  echo "[cwa-init][qt6] Qt6 compatibility already confirmed; skipping."
fi

#------------------------------------------------------------------------------------------------------------------------
#  Resolve and persist CWA version values once at container initialization
#------------------------------------------------------------------------------------------------------------------------

echo "[cwa-init] Resolving CWA versions (installed + latest stable) ..."

# Installed version baked at build time
export CWA_INSTALLED_VERSION="$(cat /app/CWA_RELEASE 2>/dev/null || echo 'v0.0.0')"
echo "[cwa-init] Installed version: $CWA_INSTALLED_VERSION"

# Latest stable release from GitHub (best-effort, fast timeout)
echo "[cwa-init] Attempting to fetch latest stable version from GitHub..."
CWA_STABLE_VERSION=""

if command -v jq >/dev/null 2>&1; then
  echo "[cwa-init] Using jq for JSON parsing..."
  if CWA_STABLE_VERSION="$(timeout 5 curl -sS --max-time 3 --connect-timeout 2 https://api.github.com/repos/crocodilestick/calibre-web-automated/releases/latest 2>/dev/null | timeout 2 jq -r '.tag_name' 2>/dev/null)"; then
    echo "[cwa-init] Successfully fetched stable version via jq: $CWA_STABLE_VERSION"
  else
    echo "[cwa-init] Failed to fetch stable version via jq (network/timeout issue)"
    CWA_STABLE_VERSION=""
  fi
else
  echo "[cwa-init] jq not available, using fallback parsing..."
  if CWA_STABLE_VERSION="$(timeout 5 curl -sS --max-time 3 --connect-timeout 2 https://api.github.com/repos/crocodilestick/calibre-web-automated/releases/latest 2>/dev/null | timeout 2 sed -n 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -n1)"; then
    echo "[cwa-init] Successfully fetched stable version via sed: $CWA_STABLE_VERSION"
  else
    echo "[cwa-init] Failed to fetch stable version via sed (network/timeout issue)"
    CWA_STABLE_VERSION=""
  fi
fi

# Validate the fetched version or use fallback
if [[ -n "$CWA_STABLE_VERSION" && "$CWA_STABLE_VERSION" =~ ^[Vv]?[0-9]+\.[0-9]+\.[0-9]+([-.][0-9A-Za-z.-]+)?$ ]]; then
  echo "[cwa-init] Valid stable version retrieved: $CWA_STABLE_VERSION"
else
  echo "[cwa-init] Invalid or missing stable version, using fallback"
  CWA_STABLE_VERSION="v0.0.0"
fi

export CWA_STABLE_VERSION

# Persist the resolved stable release for other services/processes
if printf '%s\n' "$CWA_STABLE_VERSION" > /app/CWA_STABLE_RELEASE 2>/dev/null; then
  echo "[cwa-init] Stable version persisted to /app/CWA_STABLE_RELEASE"
else
  echo "[cwa-init] WARNING: Could not persist stable version to file"
fi

echo "[cwa-init] Versions resolved: INSTALLED=$CWA_INSTALLED_VERSION, STABLE=$CWA_STABLE_VERSION"

