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

if [[ "${EUID}" -ne 0 ]]; then
  echo "Run this script as root."
  exit 1
fi

export DEBIAN_FRONTEND=noninteractive

WP_ROOT="${WP_ROOT:-/var/www/wordpress}"
DB_NAME="${DB_NAME:-wp_prod}"
DB_USER="${DB_USER:-wp_prod}"
DB_HOST="localhost"
CREDENTIALS_FILE="${CREDENTIALS_FILE:-/root/wordpress-db-credentials.txt}"
MIGRATION_DOC="${MIGRATION_DOC:-/root/WORDPRESS_MIGRATION.md}"

echo "[1/11] Installing packages..."
apt-get update
apt-get install -y \
  nginx mariadb-server redis-server \
  php8.3-fpm php8.3-cli php8.3-mysql php8.3-xml php8.3-curl php8.3-gd \
  php8.3-mbstring php8.3-zip php8.3-intl php8.3-bcmath php8.3-opcache \
  php8.3-redis php-imagick \
  certbot python3-certbot-nginx \
  unzip curl openssl

echo "[2/11] Configuring swap and kernel tuning..."
if [[ ! -f /swapfile ]]; then
  fallocate -l 2G /swapfile || dd if=/dev/zero of=/swapfile bs=1M count=2048 status=none
  chmod 600 /swapfile
  mkswap /swapfile >/dev/null
fi
if ! swapon --show | grep -q '/swapfile'; then
  swapon /swapfile
fi
if ! grep -q '^/swapfile[[:space:]]' /etc/fstab; then
  echo '/swapfile none swap sw 0 0' >> /etc/fstab
fi

cat > /etc/sysctl.d/99-wordpress-performance.conf <<'SYSCTL'
# WordPress blog performance tuning
vm.swappiness = 10
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 4096
net.ipv4.tcp_fin_timeout = 15
net.ipv4.ip_local_port_range = 10240 65535
net.ipv4.tcp_tw_reuse = 1
SYSCTL
sysctl --system >/dev/null

echo "[3/11] Tuning PHP-FPM and OPcache..."
cat > /etc/php/8.3/fpm/pool.d/zz-wordpress-performance.conf <<'PHPPOOL'
; WordPress performance overrides for this host size (4 vCPU / 8 GB RAM)
[www]
pm = dynamic
pm.max_children = 32
pm.start_servers = 6
pm.min_spare_servers = 4
pm.max_spare_servers = 10
pm.max_requests = 500
request_terminate_timeout = 120s
PHPPOOL

cat > /etc/php/8.3/fpm/conf.d/99-wordpress-performance.ini <<'PHPINI'
; WordPress performance runtime tuning
memory_limit = 256M
max_execution_time = 120
max_input_vars = 5000
post_max_size = 128M
upload_max_filesize = 128M
cgi.fix_pathinfo = 0
expose_php = Off
realpath_cache_size = 4096K
realpath_cache_ttl = 600
PHPINI

cat > /etc/php/8.3/fpm/conf.d/99-opcache-performance.ini <<'OPCACHE'
; OPcache tuning for production WordPress
opcache.enable=1
opcache.enable_cli=0
opcache.memory_consumption=256
opcache.interned_strings_buffer=32
opcache.max_accelerated_files=20000
opcache.validate_timestamps=1
opcache.revalidate_freq=60
opcache.save_comments=1
opcache.fast_shutdown=1
opcache.jit=off
OPCACHE

php-fpm8.3 -t

echo "[4/11] Tuning MariaDB..."
cat > /etc/mysql/mariadb.conf.d/60-wordpress-performance.cnf <<'MARIADB'
[mysqld]
# Connection and lookup tuning
skip-name-resolve = 1
max_connections = 150
thread_cache_size = 100
table_open_cache = 4000

# Temp table and packet sizes
tmp_table_size = 64M
max_heap_table_size = 64M
max_allowed_packet = 64M

# InnoDB tuning for 8 GB host
innodb_buffer_pool_size = 2G
innodb_buffer_pool_instances = 2
innodb_log_file_size = 512M
innodb_log_buffer_size = 64M
innodb_flush_method = O_DIRECT
innodb_flush_log_at_trx_commit = 2

# WordPress defaults
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci

# Disable legacy query cache
query_cache_type = 0
query_cache_size = 0
MARIADB

echo "[5/11] Tuning Redis for WordPress object cache..."
cat > /etc/redis/wordpress-performance.conf <<'REDIS'
# WordPress object cache tuning
bind 127.0.0.1 -::1
port 0
daemonize no
supervised systemd
unixsocket /run/redis/redis-server.sock
unixsocketperm 770
maxmemory 256mb
maxmemory-policy allkeys-lru
save ""
appendonly no
timeout 0
tcp-keepalive 300
REDIS

if ! grep -Fxq 'include /etc/redis/wordpress-performance.conf' /etc/redis/redis.conf; then
  echo 'include /etc/redis/wordpress-performance.conf' >> /etc/redis/redis.conf
fi

usermod -aG redis www-data || true

echo "[6/11] Configuring Nginx + FastCGI cache for WordPress..."
mkdir -p /var/cache/nginx/fastcgi
chown -R www-data:www-data /var/cache/nginx

mkdir -p "${WP_ROOT}"
chown -R www-data:www-data "${WP_ROOT}"

cat > /etc/nginx/conf.d/wordpress-fastcgi-cache.conf <<'NGCACHE'
# FastCGI cache for anonymous WordPress traffic
fastcgi_cache_path /var/cache/nginx/fastcgi levels=1:2 keys_zone=WORDPRESS:200m inactive=60m max_size=4g use_temp_path=off;
fastcgi_cache_key "$scheme$request_method$host$request_uri";

map $request_method $skip_cache_method {
    default 0;
    POST 1;
}

map $query_string $skip_cache_query {
    default 1;
    "" 0;
}

map $request_uri $skip_cache_uri {
    default 0;
    ~*^/wp-admin/ 1;
    ~*^/wp-login\.php$ 1;
    ~*^/wp-cron\.php$ 1;
    ~*^/xmlrpc\.php$ 1;
}

map $http_cookie $skip_cache_cookie {
    default 0;
    ~*comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_logged_in 1;
}

map "$skip_cache_method$skip_cache_query$skip_cache_uri$skip_cache_cookie" $skip_cache {
    default 0;
    ~1 1;
}
NGCACHE

cat > /etc/nginx/sites-available/wordpress.conf <<'NGSITE'
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;

    root /var/www/wordpress;
    index index.php index.html;

    access_log /var/log/nginx/wordpress.access.log;
    error_log /var/log/nginx/wordpress.error.log warn;

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

    location = /xmlrpc.php { deny all; }

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

    location ~* \.(?:css|js|jpg|jpeg|gif|png|webp|avif|ico|svg|woff|woff2|ttf)$ {
        expires 30d;
        access_log off;
        add_header Cache-Control "public, max-age=2592000, immutable";
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

        fastcgi_buffers 16 16k;
        fastcgi_buffer_size 32k;
        fastcgi_connect_timeout 60s;
        fastcgi_send_timeout 180s;
        fastcgi_read_timeout 180s;

        fastcgi_cache WORDPRESS;
        fastcgi_cache_valid 200 301 302 60m;
        fastcgi_cache_valid 404 1m;
        fastcgi_cache_use_stale error timeout invalid_header updating http_500 http_503;
        fastcgi_cache_lock on;
        fastcgi_cache_bypass $skip_cache;
        fastcgi_no_cache $skip_cache;

        add_header X-FastCGI-Cache $upstream_cache_status always;
    }

    location ~ /\.ht {
        deny all;
    }
}
NGSITE

rm -f /etc/nginx/sites-enabled/default
ln -sfn /etc/nginx/sites-available/wordpress.conf /etc/nginx/sites-enabled/wordpress.conf

if [[ ! -f "${WP_ROOT}/index.php" ]]; then
  cat > "${WP_ROOT}/index.php" <<'INDEXPHP'
<?php
http_response_code(503);
header('Content-Type: text/plain; charset=utf-8');
echo "WordPress files are not deployed yet.\n";
INDEXPHP
fi

if ! grep -q '^worker_rlimit_nofile' /etc/nginx/nginx.conf; then
  sed -i '3i worker_rlimit_nofile 200000;' /etc/nginx/nginx.conf
fi
sed -i -E 's/worker_connections[[:space:]]+[0-9]+;/worker_connections 4096;/' /etc/nginx/nginx.conf
if grep -q '# multi_accept on;' /etc/nginx/nginx.conf; then
  sed -i 's/# multi_accept on;/multi_accept on;/' /etc/nginx/nginx.conf
elif ! grep -q 'multi_accept on;' /etc/nginx/nginx.conf; then
  sed -i '/worker_connections 4096;/a\    multi_accept on;' /etc/nginx/nginx.conf
fi

nginx -t

echo "[7/11] Raising file descriptor limits for Nginx and PHP-FPM..."
mkdir -p /etc/systemd/system/nginx.service.d /etc/systemd/system/php8.3-fpm.service.d

cat > /etc/systemd/system/nginx.service.d/override.conf <<'NGOVR'
[Service]
LimitNOFILE=200000
NGOVR

cat > /etc/systemd/system/php8.3-fpm.service.d/override.conf <<'PHPOVR'
[Service]
LimitNOFILE=200000
PHPOVR

systemctl daemon-reload

echo "[8/11] Installing WP-CLI..."
curl -fsSL -o /usr/local/bin/wp https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
chmod +x /usr/local/bin/wp

echo "[9/11] Restarting services and validating..."
systemctl restart php8.3-fpm mariadb redis-server nginx
systemctl is-active php8.3-fpm mariadb redis-server nginx >/dev/null

echo "[10/11] Creating WordPress database and credentials..."
DB_PASS=""
if [[ -f "${CREDENTIALS_FILE}" ]]; then
  DB_PASS="$(grep -E '^WORDPRESS_DB_PASSWORD=' "${CREDENTIALS_FILE}" | head -n1 | cut -d'=' -f2- || true)"
fi
if [[ -z "${DB_PASS}" ]]; then
  DB_PASS="$(openssl rand -base64 32 | tr -dc 'A-Za-z0-9' | head -c 24)"
fi

mariadb <<SQL
CREATE DATABASE IF NOT EXISTS \`${DB_NAME}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS '${DB_USER}'@'localhost' IDENTIFIED BY '${DB_PASS}';
ALTER USER '${DB_USER}'@'localhost' IDENTIFIED BY '${DB_PASS}';
GRANT ALL PRIVILEGES ON \`${DB_NAME}\`.* TO '${DB_USER}'@'localhost';
FLUSH PRIVILEGES;
SQL

install -m 600 /dev/null "${CREDENTIALS_FILE}"
cat > "${CREDENTIALS_FILE}" <<CREDS
WORDPRESS_DB_NAME=${DB_NAME}
WORDPRESS_DB_USER=${DB_USER}
WORDPRESS_DB_PASSWORD=${DB_PASS}
WORDPRESS_DB_HOST=${DB_HOST}
CREDS

echo "[11/11] Writing migration runbook..."
cat > "${MIGRATION_DOC}" <<'MIGRATION'
# WordPress Migration Steps (This Server)

## 1) Put old site in maintenance mode and copy files

```bash
# From OLD server (recommended):
rsync -aHAX --delete /path/to/old/wp/ root@NEW_SERVER_IP:/var/www/wordpress/
```

Then on new server:

```bash
chown -R www-data:www-data /var/www/wordpress
find /var/www/wordpress -type d -exec chmod 755 {} \;
find /var/www/wordpress -type f -exec chmod 644 {} \;
```

## 2) Export and import database

```bash
# On old server:
mysqldump --single-transaction --quick --routines --triggers --events OLD_DB > old-db.sql
scp old-db.sql root@NEW_SERVER_IP:/root/

# On new server:
mariadb wp_prod < /root/old-db.sql
```

## 3) Update wp-config.php with new DB + Redis socket

Set these values:

```php
define('DB_NAME', 'wp_prod');
define('DB_USER', 'wp_prod');
define('DB_PASSWORD', 'REPLACE_ME');
define('DB_HOST', 'localhost');

define('WP_REDIS_HOST', '127.0.0.1');
define('WP_REDIS_PORT', 0);
define('WP_REDIS_PATH', '/run/redis/redis-server.sock');
define('WP_CACHE_KEY_SALT', 'yourdomain.com:');
```

## 4) Set domain and issue SSL

Edit `/etc/nginx/sites-available/wordpress.conf` and set:

```nginx
server_name yourdomain.com www.yourdomain.com;
```

Then:

```bash
nginx -t && systemctl reload nginx
certbot --nginx -d yourdomain.com -d www.yourdomain.com --redirect -m you@example.com --agree-tos -n
```

## 5) Finalize with WP-CLI

```bash
cd /var/www/wordpress
wp search-replace 'https://old-domain.com' 'https://yourdomain.com' --skip-columns=guid --allow-root
wp cache flush --allow-root
```

## 6) Enable WordPress object cache plugin

Install "Redis Object Cache" plugin in wp-admin and click Enable Cache.

## 7) Quick health checks

```bash
curl -I https://yourdomain.com
redis-cli -s /run/redis/redis-server.sock ping
mariadb -e "SHOW DATABASES LIKE 'wp_prod';"
```
MIGRATION

chmod 600 "${MIGRATION_DOC}"

echo
printf '%s\n' "Setup complete."
printf '%s\n' "DB credentials: ${CREDENTIALS_FILE}"
printf '%s\n' "Migration runbook: ${MIGRATION_DOC}"
printf '%s\n' "WordPress root: ${WP_ROOT}"
printf '%s\n' "Run: nginx -t && systemctl reload nginx after any domain edits."
