#!/bin/bash
set -euo pipefail

# Debian 12 -> Debian 13 upgrade script (optional PHP/nginx handling)
# Usage:
#   ./upgrade_to_debian13.sh [--auto] [--with-php] [--with-nginx] [--php-version 8.2]
#                            [--php-nginx-only] [--force] [--dry-run] [--help]
#
# Defaults:
#   - if system is bookworm: do system upgrade
#   - if system is already trixie and no actions were requested: do nothing and exit 0
#   - php-version: 8.2 (only if PHP enabled)

export DEBIAN_FRONTEND=noninteractive

PHP_VERSION_DEFAULT="8.2"
PHP_VERSION="$PHP_VERSION_DEFAULT"

WITH_PHP=0
WITH_NGINX=0
AUTO=0
FORCE=0
DRY_RUN=0
PHP_NGINX_ONLY=0

log() { echo "[$(date +'%F %T')] $*"; }
die() { echo "ERROR: $*" >&2; exit 1; }

run() {
  if [ "$DRY_RUN" -eq 1 ]; then
    echo "[DRY-RUN] $*"
  else
    eval "$@"
  fi
}

usage() {
  cat <<'EOF'
Debian 12 -> Debian 13 (trixie) upgrade, optional PHP + nginx adjustments.

Options:
  --auto                 Auto-detect PHP usage (nginx + fastcgi_pass php) and enable --with-php --with-nginx if detected.
  --with-php             Install/upgrade PHP to selected version (default 8.2) using Sury repo.
  --with-nginx           Update nginx configs (php-fpm socket path), test nginx config, reload nginx. Requires --with-php.
  --php-version X.Y      PHP version (e.g. 8.2, 8.3). Only used with --with-php.
  --php-nginx-only       Skip Debian release upgrade; do only PHP/nginx actions (useful if system already on trixie).
  --force                Proceed even if Debian version isn't detected as 12 (bookworm). (Use carefully)
  --dry-run              Print actions without executing.
  --help                 Show this help.

Examples:
  # System-only upgrade (on Debian 12):
  ./upgrade_to_debian13.sh

  # Auto-detect PHP usage and update PHP + nginx only if needed:
  ./upgrade_to_debian13.sh --auto

  # Force enable PHP + nginx update:
  ./upgrade_to_debian13.sh --with-php --with-nginx --php-version 8.2

  # If you're already on Debian 13 and only want PHP/nginx fix:
  ./upgrade_to_debian13.sh --php-nginx-only --with-php --with-nginx

Behavior note:
  - If system is already Debian 13 (trixie) and you run the script without flags,
    it will do nothing and exit successfully.

Common mistakes:
  - ./upgrade_to_debian13.sh --with-nginx
    -> ERROR (nginx changes require PHP flag)
  - ./upgrade_to_debian13.sh --php-version 8.2
    -> ERROR (php-version makes sense only with --with-php)
EOF
}

# -------------------------
# Parse args
# -------------------------
while [ $# -gt 0 ]; do
  case "$1" in
    --auto) AUTO=1; shift ;;
    --with-php) WITH_PHP=1; shift ;;
    --with-nginx) WITH_NGINX=1; shift ;;
    --php-version)
      shift
      [ $# -gt 0 ] || { echo; echo "ERROR: --php-version requires a value (e.g. 8.2)"; echo; usage; exit 1; }
      PHP_VERSION="$1"
      shift
      ;;
    --php-nginx-only) PHP_NGINX_ONLY=1; shift ;;
    --force) FORCE=1; shift ;;
    --dry-run) DRY_RUN=1; shift ;;
    --help|-h) usage; exit 0 ;;
    *)
      echo
      echo "ERROR: Unknown argument: $1"
      echo
      usage
      exit 1
      ;;
  esac
done

# -------------------------
# Validate args
# -------------------------
if [ "$WITH_NGINX" -eq 1 ] && [ "$WITH_PHP" -ne 1 ]; then
  echo
  echo "ERROR: You used --with-nginx but not --with-php."
  echo "Fix:   ./upgrade_to_debian13.sh --with-php --with-nginx (or --auto)"
  echo
  usage
  exit 1
fi

if [ "$PHP_VERSION" != "$PHP_VERSION_DEFAULT" ] && [ "$WITH_PHP" -ne 1 ]; then
  echo
  echo "ERROR: You set --php-version but didn't enable --with-php."
  echo "Fix:   ./upgrade_to_debian13.sh --with-php --php-version ${PHP_VERSION}"
  echo
  usage
  exit 1
fi

# -------------------------
# Detect Debian version
# -------------------------
DEB_CODENAME="unknown"
if [ -r /etc/os-release ]; then
  . /etc/os-release
  DEB_CODENAME="${VERSION_CODENAME:-unknown}"
fi

# Did user request any "actions" besides system upgrade?
REQUESTED_ACTIONS=0
if [ "$WITH_PHP" -eq 1 ] || [ "$WITH_NGINX" -eq 1 ] || [ "$AUTO" -eq 1 ]; then
  REQUESTED_ACTIONS=1
fi

# If already on trixie:
# - no flags -> do nothing, exit 0
# - flags present -> automatically switch to php-nginx-only mode
if [ "$DEB_CODENAME" = "trixie" ]; then
  if [ "$REQUESTED_ACTIONS" -eq 0 ]; then
    log "Detected Debian codename: trixie (already Debian 13)."
    log "No actions requested (no flags). Nothing to do. Exiting."
    exit 0
  fi
  if [ "$PHP_NGINX_ONLY" -eq 0 ]; then
    log "Detected Debian codename: trixie (already Debian 13)."
    log "Actions requested -> enabling --php-nginx-only automatically (skipping release upgrade)."
    PHP_NGINX_ONLY=1
  fi
fi

# If not bookworm and not trixie, require --force unless php-nginx-only
if [ "$PHP_NGINX_ONLY" -eq 0 ] && [ "$FORCE" -eq 0 ] && [ "$DEB_CODENAME" != "bookworm" ]; then
  echo
  echo "ERROR: This script expects Debian 12 (bookworm) for release upgrade."
  echo "Detected: ${DEB_CODENAME}"
  echo
  echo "Possible actions:"
  echo
  echo "  1) Show help:"
  echo "     ./upgrade_to_debian13.sh --help"
  echo
  echo "  2) Force run anyway (NOT recommended unless you know what you're doing):"
  echo "     ./upgrade_to_debian13.sh --force"
  echo
  usage
  exit 1
fi

# -------------------------
# Auto-detect PHP usage (works in both modes)
# -------------------------
if [ "$AUTO" -eq 1 ]; then
  log "AUTO mode: checking for nginx + fastcgi_pass php..."
  USES_PHP=0
  if command -v nginx >/dev/null 2>&1; then
    if grep -R "fastcgi_pass" /etc/nginx 2>/dev/null | grep -qi "php"; then
      USES_PHP=1
    fi
  fi

  if [ "$USES_PHP" -eq 1 ]; then
    log "AUTO: PHP usage detected -> enabling --with-php and --with-nginx"
    WITH_PHP=1
    WITH_NGINX=1
  else
    log "AUTO: PHP not detected -> no PHP/nginx changes"
  fi
fi

log "=== Starting ==="
log "Detected Debian codename: ${DEB_CODENAME}"
log "Mode: PHP_NGINX_ONLY=$PHP_NGINX_ONLY WITH_PHP=$WITH_PHP WITH_NGINX=$WITH_NGINX PHP_VERSION=$PHP_VERSION DRY_RUN=$DRY_RUN"

# -------------------------
# Debian release upgrade (optional)
# -------------------------
if [ "$PHP_NGINX_ONLY" -eq 0 ]; then
  log "Setting dpkg policy: keep old configs (confold/confdef)"
  run "cat > /etc/apt/apt.conf.d/90force-conf <<'EOF'
DPkg::Options {
   \"--force-confdef\";
   \"--force-confold\";
};
EOF"

  log "Backing up /etc/apt/sources.list"
  run "cp /etc/apt/sources.list /etc/apt/sources.list.backup.$(date +%F_%T) || true"

  log "Updating sources.list to Debian 13 (trixie)"
  run "cat > /etc/apt/sources.list <<'EOF'
deb http://ftp.debian.org/debian trixie main contrib non-free non-free-firmware
deb http://ftp.debian.org/debian trixie-updates main contrib non-free non-free-firmware
deb http://security.debian.org/debian-security trixie-security main contrib non-free non-free-firmware
EOF"

  log "apt update"
  run "apt update"

  log "apt full-upgrade"
  run "apt full-upgrade -y || (apt --fix-broken install -y && apt full-upgrade -y)"

  log "apt autoremove/autoclean"
  run "apt autoremove -y"
  run "apt autoclean -y"

  log "=== Base system upgrade done ==="
else
  log "Skipping Debian release upgrade (--php-nginx-only enabled)"
fi

# -------------------------
# Optional PHP install/upgrade
# -------------------------
if [ "$WITH_PHP" -eq 1 ]; then
  log "=== PHP enabled: installing PHP ${PHP_VERSION} via Sury repo ==="

  run "apt install -y ca-certificates apt-transport-https curl lsb-release gnupg"

  run "curl -fsSL https://packages.sury.org/php/apt.gpg | tee /usr/share/keyrings/sury-php.gpg >/dev/null"
  run "echo \"deb [signed-by=/usr/share/keyrings/sury-php.gpg] https://packages.sury.org/php/ trixie main\" > /etc/apt/sources.list.d/sury-php.list"

  run "apt update"

  run "apt install -y \
    php${PHP_VERSION} php${PHP_VERSION}-fpm php${PHP_VERSION}-cli \
    php${PHP_VERSION}-mysql php${PHP_VERSION}-xml php${PHP_VERSION}-mbstring \
    php${PHP_VERSION}-intl php${PHP_VERSION}-gd php${PHP_VERSION}-curl \
    php${PHP_VERSION}-zip php${PHP_VERSION}-apcu"

  log "PHP ${PHP_VERSION} installation done"
fi

# -------------------------
# Optional nginx socket update
# -------------------------
if [ "$WITH_NGINX" -eq 1 ]; then
  command -v nginx >/dev/null 2>&1 || die "nginx not found, but --with-nginx was set."

  log "=== nginx enabled: updating fastcgi php-fpm socket paths to php${PHP_VERSION}-fpm.sock ==="

  run "find /etc/nginx -type f -name \"*.conf\" -exec sed -i \
    -e 's|php[0-9.]*-fpm.sock|php${PHP_VERSION}-fpm.sock|g' \
    -e 's|/var/run/php/php[0-9.]*-fpm.sock|/run/php/php${PHP_VERSION}-fpm.sock|g' \
    -e 's|/run/php/php[0-9.]*-fpm.sock|/run/php/php${PHP_VERSION}-fpm.sock|g' {} +"

  log "Testing nginx config"
  run "nginx -t"

  log "Restart/reload services (LXC-friendly)"
  run "service php${PHP_VERSION}-fpm restart || true"
  run "service nginx reload || service nginx restart || true"

  log "nginx update done"
fi

log "=== DONE ==="
