#!/usr/bin/env bash
# Ubuntu 24.04: nginx + MariaDB + PHP-FPM + WordPress + домен + Let's Encrypt
# Домен должен уже указывать на IP сервера. Порты 80/443 открыты.

set -euo pipefail

if [[ "${EUID}" -ne 0 ]]; then
  >&2 echo "This script requires root level access to run"
  exit 1
fi

require_var() {
  local v="$1"
  if [[ -z "${!v:-}" ]]; then
    >&2 echo "$v must be set"
    exit 1
  fi
}

require_var WORDPRESS_DB_PASSWORD
require_var WORDPRESS_ADMIN_USER
require_var WORDPRESS_ADMIN_PASSWORD
require_var WORDPRESS_ADMIN_EMAIL
require_var WORDPRESS_URL
require_var WORDPRESS_SITE_TITLE

export DEBIAN_FRONTEND="noninteractive"

WORDPRESS_DB_NAME="${WORDPRESS_DB_NAME:-wordpress}"
WORDPRESS_DB_USER="${WORDPRESS_DB_USER:-wordpress}"
WORDPRESS_PATH="${WORDPRESS_PATH:-/var/www/wordpress}"
UPLOAD_MAX_FILESIZE="${UPLOAD_MAX_FILESIZE:-200M}"
WORDPRESS_CLI_VERSION="${WORDPRESS_CLI_VERSION:-2.11.0}"

TLS_HOSTNAME="$(echo "${WORDPRESS_URL}" | awk -F[/:] '{print $4}')"
if [[ -z "${TLS_HOSTNAME}" ]]; then
  >&2 echo "Failed to parse hostname from WORDPRESS_URL='${WORDPRESS_URL}'. Use like https://example.com"
  exit 1
fi

NGINX_SITE_AVAILABLE="/etc/nginx/sites-available/${TLS_HOSTNAME}.conf"
NGINX_SITE_ENABLED="/etc/nginx/sites-enabled/${TLS_HOSTNAME}.conf"
CERT_DIR="/etc/letsencrypt/live/${TLS_HOSTNAME}"

write_nginx_http_only() {
  cat > "${NGINX_SITE_AVAILABLE}" <<EOF
server {
    listen 80;
    listen [::]:80;
    server_name ${TLS_HOSTNAME};

    # ACME challenge
    location ^~ /.well-known/acme-challenge/ {
        root /var/www/certbot;
        default_type "text/plain";
    }

    location / {
        # пока без редиректа на https, чтобы certbot/nginx-плагин работал стабильно
        try_files \$uri \$uri/ =404;
    }
}
EOF
}

write_nginx_https() {
  cat > "${NGINX_SITE_AVAILABLE}" <<EOF
server {
    listen 80;
    listen [::]:80;
    server_name ${TLS_HOSTNAME};

    location ^~ /.well-known/acme-challenge/ {
        root /var/www/certbot;
        default_type "text/plain";
    }

    location / {
        return 301 https://\$host\$request_uri;
    }
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name ${TLS_HOSTNAME};

    root ${WORDPRESS_PATH};
    index index.php index.html;

    client_max_body_size ${UPLOAD_MAX_FILESIZE};

    ssl_certificate     ${CERT_DIR}/fullchain.pem;
    ssl_certificate_key ${CERT_DIR}/privkey.pem;

    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    location / {
        try_files \$uri \$uri/ /index.php?\$args;
    }

    location ~ \.php\$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:${PHP_FPM_SOCK};
        fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~* /(?:uploads|files)/.*\.php\$ { deny all; }
    location ~* ^/(?:wp-content|wp-includes)/.*\.php\$ { deny all; }
    location ~* wp-config.php { deny all; }
    location ~ /\. { deny all; }

    location = /favicon.ico { log_not_found off; access_log off; }
    location = /robots.txt  { allow all; log_not_found off; access_log off; }
}
EOF
}

echo "▶ Setting hostname (optional)"
if [[ "$(hostname)" != "${TLS_HOSTNAME}" ]]; then
  hostnamectl set-hostname "${TLS_HOSTNAME}"
fi
if ! grep -q "${TLS_HOSTNAME}" /etc/hosts; then
  printf "::1 %s\n127.0.0.1 %s\n" "${TLS_HOSTNAME}" "${TLS_HOSTNAME}" >> /etc/hosts
fi

echo "▶ Installing packages"
apt-get update -qq
apt-get install -y -qq --no-install-recommends \
  ca-certificates curl gnupg lsb-release unzip \
  nginx \
  mariadb-server \
  php-fpm php-cli php-common \
  php-bcmath php-curl php-gd php-imagick php-mbstring php-mysql php-opcache php-xml php-zip \
  ghostscript \
  certbot python3-certbot-nginx

systemctl enable --now mariadb
systemctl enable --now nginx

PHP_FPM_SOCK="$(find /run/php -maxdepth 1 -type s -name 'php*-fpm.sock' | sort -V | tail -n1 || true)"
if [[ -z "${PHP_FPM_SOCK}" ]]; then
  >&2 echo "Cannot find PHP-FPM socket in /run/php. Is php-fpm installed and running?"
  systemctl status php*-fpm --no-pager || true
  exit 1
fi

PHP_VERSION="$(php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION;')"
PHP_OVERRIDE_INI="/etc/php/${PHP_VERSION}/fpm/conf.d/30-wordpress-overrides.ini"

echo "▶ Configuring PHP-FPM overrides"
cat > "${PHP_OVERRIDE_INI}" <<EOF
upload_max_filesize=${UPLOAD_MAX_FILESIZE}
post_max_size=${UPLOAD_MAX_FILESIZE}
memory_limit=200M
max_execution_time=300
EOF
systemctl restart "php${PHP_VERSION}-fpm"

echo "▶ Configuring MariaDB for WordPress"
mysql -uroot <<SQL
CREATE DATABASE IF NOT EXISTS \`${WORDPRESS_DB_NAME}\` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS '${WORDPRESS_DB_USER}'@'localhost' IDENTIFIED BY '${WORDPRESS_DB_PASSWORD}';
GRANT ALL PRIVILEGES ON \`${WORDPRESS_DB_NAME}\`.* TO '${WORDPRESS_DB_USER}'@'localhost';
FLUSH PRIVILEGES;
SQL

echo "▶ Installing wp-cli"
if [[ ! -x /usr/local/bin/wp ]]; then
  curl -fsSL "https://github.com/wp-cli/wp-cli/releases/download/v${WORDPRESS_CLI_VERSION}/wp-cli-${WORDPRESS_CLI_VERSION}.phar" -o /usr/local/bin/wp
  chmod +x /usr/local/bin/wp
fi

echo "▶ Preparing WordPress dir: ${WORDPRESS_PATH}"
mkdir -p "${WORDPRESS_PATH}"
chown -R www-data:www-data "$(dirname "${WORDPRESS_PATH}")"

if [[ ! -f "${WORDPRESS_PATH}/wp-settings.php" ]]; then
  echo "▶ Downloading WordPress"
  sudo -u www-data -H wp --path="${WORDPRESS_PATH}" core download --locale=en_US
fi

if [[ ! -f "${WORDPRESS_PATH}/wp-config.php" ]]; then
  echo "▶ Creating wp-config.php"
  sudo -u www-data -H wp --path="${WORDPRESS_PATH}" config create \
    --dbname="${WORDPRESS_DB_NAME}" \
    --dbuser="${WORDPRESS_DB_USER}" \
    --dbpass="${WORDPRESS_DB_PASSWORD}" \
    --dbhost="localhost" \
    --skip-check \
    --extra-php <<'PHP'
if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && strpos($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false) {
  $_SERVER['HTTPS'] = 'on';
}
if (!empty($_SERVER['HTTP_X_FORWARDED_HOST'])) {
  $_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_HOST'];
}
define('FORCE_SSL_ADMIN', true);
PHP
fi

if ! sudo -u www-data -H wp --path="${WORDPRESS_PATH}" core is-installed >/dev/null 2>&1; then
  echo "▶ Installing WordPress site"
  sudo -u www-data -H wp --path="${WORDPRESS_PATH}" core install \
    --url="${WORDPRESS_URL}" \
    --title="${WORDPRESS_SITE_TITLE}" \
    --admin_user="${WORDPRESS_ADMIN_USER}" \
    --admin_password="${WORDPRESS_ADMIN_PASSWORD}" \
    --admin_email="${WORDPRESS_ADMIN_EMAIL}" \
    --skip-email

  sudo -u www-data -H wp --path="${WORDPRESS_PATH}" option update permalink_structure '/%year%/%monthnum%/%postname%/'
fi

echo "▶ Setting permissions"
find "${WORDPRESS_PATH}" -type d -exec chmod 2755 {} \;
find "${WORDPRESS_PATH}" -type f -exec chmod 0644 {} \;
chown -R www-data:www-data "${WORDPRESS_PATH}"
chmod -R 0775 "${WORDPRESS_PATH}/wp-content"

echo "▶ Configuring nginx (HTTP-only first)"
mkdir -p /var/www/certbot
chown -R www-data:www-data /var/www/certbot

# disable default site
rm -f /etc/nginx/sites-enabled/default || true

write_nginx_http_only
ln -sf "${NGINX_SITE_AVAILABLE}" "${NGINX_SITE_ENABLED}"

nginx -t
systemctl reload nginx

if [[ "${LETS_ENCRYPT_STAGING:-0}" == "1" ]]; then
  CERTBOT_STAGING_FLAG="--staging"
else
  CERTBOT_STAGING_FLAG=""
fi

if [[ ! -f "${CERT_DIR}/fullchain.pem" ]]; then
  echo "▶ Issuing Let's Encrypt certificate for ${TLS_HOSTNAME}"
  # ВАЖНО: используем webroot, чтобы nginx не требовал SSL-конфига до сертификата
  if ! certbot certonly --webroot \
    -w /var/www/certbot \
    -d "${TLS_HOSTNAME}" \
    -m "${WORDPRESS_ADMIN_EMAIL}" \
    --agree-tos --non-interactive \
    ${CERTBOT_STAGING_FLAG} 2>&1; then
    >&2 echo "Ошибка получения сертификата"
    exit 1
  fi
  echo "▶ SSL certificate issued successfully"
fi

echo "▶ Enabling HTTPS config"
write_nginx_https
nginx -t
systemctl reload nginx

# Auto-renewal timer (обычно уже есть)
systemctl enable --now certbot.timer >/dev/null 2>&1 || true

echo "▶ Done"
echo "URL: ${WORDPRESS_URL}"
echo "Domain: ${TLS_HOSTNAME}"
echo "WP path: ${WORDPRESS_PATH}"
