#!/usr/bin/env bash
set -euo pipefail

PHP_VERSION="${PHP_VERSION:-8.2}"
PHP_INI="${PHP_INI:-/etc/php/${PHP_VERSION}/fpm/php.ini}"
POOL_CONF="${POOL_CONF:-/etc/php/${PHP_VERSION}/fpm/pool.d/www.conf}"
FPM_TEST_BIN="${FPM_TEST_BIN:-php-fpm${PHP_VERSION}}"

MEMORY_LIMIT="${MEMORY_LIMIT:-256M}"
MAX_EXECUTION_TIME="${MAX_EXECUTION_TIME:-120}"
MAX_INPUT_TIME="${MAX_INPUT_TIME:-120}"
POST_MAX_SIZE="${POST_MAX_SIZE:-50M}"
UPLOAD_MAX_FILESIZE="${UPLOAD_MAX_FILESIZE:-50M}"

PM_MAX_CHILDREN="${PM_MAX_CHILDREN:-4}"
PM_START_SERVERS="${PM_START_SERVERS:-2}"
PM_MIN_SPARE_SERVERS="${PM_MIN_SPARE_SERVERS:-1}"
PM_MAX_SPARE_SERVERS="${PM_MAX_SPARE_SERVERS:-2}"
PM_MAX_REQUESTS="${PM_MAX_REQUESTS:-200}"

RESTART_SERVICES=0

usage() {
  cat <<EOF
Uso: $(basename "$0") [--restart]

Aplica limites recomendados ao PHP-FPM para o droplet atual.

Opcoes:
  --restart   Reinicia php${PHP_VERSION}-fpm e apache2 ao final.
  -h, --help  Exibe esta ajuda.

Variaveis de ambiente suportadas:
  PHP_VERSION, PHP_INI, POOL_CONF, FPM_TEST_BIN
  MEMORY_LIMIT, MAX_EXECUTION_TIME, MAX_INPUT_TIME
  POST_MAX_SIZE, UPLOAD_MAX_FILESIZE
  PM_MAX_CHILDREN, PM_START_SERVERS, PM_MIN_SPARE_SERVERS,
  PM_MAX_SPARE_SERVERS, PM_MAX_REQUESTS
EOF
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    --restart)
      RESTART_SERVICES=1
      shift
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      echo "Argumento invalido: $1" >&2
      usage >&2
      exit 1
      ;;
  esac
done

require_root() {
  if [[ "${EUID:-$(id -u)}" -ne 0 ]]; then
    echo "Execute como root ou com sudo." >&2
    exit 1
  fi
}

require_file() {
  local file_path="$1"

  if [[ ! -f "$file_path" ]]; then
    echo "Arquivo nao encontrado: $file_path" >&2
    exit 1
  fi
}

backup_file() {
  local file_path="$1"
  local backup_path="${file_path}.bak.$(date +%Y%m%d_%H%M%S)"

  cp "$file_path" "$backup_path"
  echo "Backup criado: $backup_path"
}

set_ini_value() {
  local file_path="$1"
  local key="$2"
  local value="$3"

  if grep -Eq "^[;[:space:]]*${key}[[:space:]]*=" "$file_path"; then
    sed -Ei "s|^[;[:space:]]*${key}[[:space:]]*=.*|${key} = ${value}|" "$file_path"
  else
    printf '\n%s = %s\n' "$key" "$value" >> "$file_path"
  fi
}

set_pool_value() {
  local file_path="$1"
  local key="$2"
  local value="$3"

  if grep -Eq "^[;[:space:]]*${key}[[:space:]]*=" "$file_path"; then
    sed -Ei "s|^[;[:space:]]*${key}[[:space:]]*=.*|${key} = ${value}|" "$file_path"
  else
    printf '\n%s = %s\n' "$key" "$value" >> "$file_path"
  fi
}

test_fpm_config() {
  if command -v "$FPM_TEST_BIN" >/dev/null 2>&1; then
    "$FPM_TEST_BIN" -t
    return
  fi

  echo "Aviso: binario de teste nao encontrado: $FPM_TEST_BIN" >&2
  echo "Valide manualmente com o binario correto do php-fpm." >&2
}

restart_services() {
  local fpm_service="php${PHP_VERSION}-fpm"

  systemctl restart "$fpm_service"
  systemctl restart apache2

  systemctl status "$fpm_service" --no-pager || true
  systemctl status apache2 --no-pager || true
}

print_summary() {
  echo
  echo "Limites aplicados em: $PHP_INI"
  grep -E '^(memory_limit|max_execution_time|max_input_time|post_max_size|upload_max_filesize)[[:space:]]*=' "$PHP_INI" || true
  echo
  echo "Pool aplicado em: $POOL_CONF"
  grep -E '^(pm.max_children|pm.start_servers|pm.min_spare_servers|pm.max_spare_servers|pm.max_requests)[[:space:]]*=' "$POOL_CONF" || true
}

require_root
require_file "$PHP_INI"
require_file "$POOL_CONF"

backup_file "$PHP_INI"
backup_file "$POOL_CONF"

set_ini_value "$PHP_INI" "memory_limit" "$MEMORY_LIMIT"
set_ini_value "$PHP_INI" "max_execution_time" "$MAX_EXECUTION_TIME"
set_ini_value "$PHP_INI" "max_input_time" "$MAX_INPUT_TIME"
set_ini_value "$PHP_INI" "post_max_size" "$POST_MAX_SIZE"
set_ini_value "$PHP_INI" "upload_max_filesize" "$UPLOAD_MAX_FILESIZE"

set_pool_value "$POOL_CONF" "pm.max_children" "$PM_MAX_CHILDREN"
set_pool_value "$POOL_CONF" "pm.start_servers" "$PM_START_SERVERS"
set_pool_value "$POOL_CONF" "pm.min_spare_servers" "$PM_MIN_SPARE_SERVERS"
set_pool_value "$POOL_CONF" "pm.max_spare_servers" "$PM_MAX_SPARE_SERVERS"
set_pool_value "$POOL_CONF" "pm.max_requests" "$PM_MAX_REQUESTS"

test_fpm_config
print_summary

if [[ "$RESTART_SERVICES" -eq 1 ]]; then
  restart_services
fi

echo
echo "Concluido."