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

# Backfill the WHP-patched wp-cli-login-server.php mu-plugin and the native
# magic-login create-script across every WordPress site WHP manages.
#
# Why: the upstream mu-plugin (1.5) calls `is_admin()` from inside namespace
# WP_CLI_Login. On PHP 8.5 PHP doesn't fall back to the global `is_admin`,
# so the mu-plugin fatals on every front-end request — observed on 32+
# customer sites in production. The patched mu-plugin in WHP fixes that;
# the native create-script replaces `wp login create` for token issuance
# and replaces `wp login install --mu` for mu-plugin provisioning.
#
# We deliberately do NOT uninstall the upstream `aaemnnosttv/wp-cli-login-command`
# package. An earlier version of this script tried — but `wp package uninstall`
# refuses to remove packages installed from git source if their vendor dir has
# any uncommitted state (composer's safety net), and falling back to `rm -rf`
# leaves the wp-cli autoloader pointing at missing files, which fatals every
# subsequent `wp` invocation on that site (broke 17 sites on whp01 once).
# The package staying installed is harmless: WHP no longer calls `wp login`
# anywhere on the warm path, and the package's own copy of the mu-plugin only
# ships into wp-content/ if someone runs `wp login install --mu` manually.
#
# Source of truth: the `whp.wordpress_sites` table. WHP only ever installed
# the broken mu-plugin via `installWordPress()` / `importWordPress()` /
# `createLoginToken()`, all of which register the site in this table — so
# any site with the broken file is in the DB. We don't walk the filesystem
# to avoid touching unmanaged directories.
#
# Idempotent: re-running this script is a no-op once every site is up to
# date. Detection is by sha256 vs the tarball-shipped templates.

# update.sh runs per-version scripts BEFORE rsyncing web-files/, so the
# tarball-shipped templates are at a path relative to this script, NOT at
# /docker/whp/web/ (which still has the old version at this point).
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
TARBALL_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
SRC_MUPLUGIN="$TARBALL_ROOT/web-files/templates/mu-plugins/wp-cli-login-server.php"
SRC_CREATESCRIPT="$TARBALL_ROOT/web-files/templates/site-private/whp-magic-login-create.php"

[ -f "$SRC_MUPLUGIN" ]     || { echo "FATAL: mu-plugin template missing at $SRC_MUPLUGIN" >&2; exit 1; }
[ -f "$SRC_CREATESCRIPT" ] || { echo "FATAL: create-script template missing at $SRC_CREATESCRIPT" >&2; exit 1; }
[ -r /root/.my.cnf ]       || { echo "FATAL: /root/.my.cnf not readable; cannot reach whp DB" >&2; exit 1; }

SRC_MUHASH="$(sha256sum "$SRC_MUPLUGIN"     | awk '{print $1}')"
SRC_CRHASH="$(sha256sum "$SRC_CREATESCRIPT" | awk '{print $1}')"

count_total=0
count_no_dir=0
count_no_wp=0
count_mu_already=0
count_mu_replaced=0
count_mu_unrecognized=0
count_cs_already=0
count_cs_dropped=0

# Pull every WHP-managed WP site. Active + inactive + maintenance — all of
# them might still have the broken mu-plugin fataling on page hits.
# Use tab as the delimiter (-B) and strip the header (-N).
sites_tsv="$(mysql --defaults-file=/root/.my.cnf -N -B \
    -e "SELECT user, domain FROM whp.wordpress_sites" 2>/dev/null || true)"

if [ -z "$sites_tsv" ]; then
    echo "no rows in whp.wordpress_sites — nothing to do" >&2
    exit 0
fi

# Iterate. IFS=tab; readarray-style loop that's robust to spaces in fields.
while IFS=$'\t' read -r user domain; do
    [ -z "${user:-}" ] && continue
    count_total=$((count_total+1))

    # /docker/users/<user>/<domain>/public_html is the bind-mount target for
    # the container's /home/<user>/public_html. We can operate on it from
    # the host directly, no docker exec needed for the file drops.
    site_dir="/docker/users/$user/$domain/public_html"
    if [ ! -d "$site_dir" ]; then
        echo "SKIP $domain — host dir missing: $site_dir"
        count_no_dir=$((count_no_dir+1))
        continue
    fi
    if [ ! -f "$site_dir/wp-load.php" ]; then
        echo "SKIP $domain — no wp-load.php at $site_dir"
        count_no_wp=$((count_no_wp+1))
        continue
    fi

    owner_uid="$(stat -c '%u' "$site_dir")"
    owner_gid="$(stat -c '%g' "$site_dir")"

    # ----- mu-plugin -----
    mu_target="$site_dir/wp-content/mu-plugins/wp-cli-login-server.php"
    mu_dir="$(dirname "$mu_target")"
    mkdir -p "$mu_dir"
    chown "$owner_uid:$owner_gid" "$mu_dir" 2>/dev/null || true

    if [ -f "$mu_target" ]; then
        cur_hash="$(sha256sum "$mu_target" | awk '{print $1}')"
        if [ "$cur_hash" = "$SRC_MUHASH" ]; then
            count_mu_already=$((count_mu_already+1))
        elif grep -q 'namespace WP_CLI_Login' "$mu_target"; then
            install -m 0644 -o "$owner_uid" -g "$owner_gid" "$SRC_MUPLUGIN" "$mu_target"
            count_mu_replaced=$((count_mu_replaced+1))
            echo "PATCHED mu-plugin: $domain"
        else
            count_mu_unrecognized=$((count_mu_unrecognized+1))
            echo "SKIP mu-plugin (foreign content): $mu_target"
        fi
    else
        install -m 0644 -o "$owner_uid" -g "$owner_gid" "$SRC_MUPLUGIN" "$mu_target"
        count_mu_replaced=$((count_mu_replaced+1))
        echo "INSTALLED mu-plugin: $domain"
    fi

    # ----- create-script -----
    cs_dir="$site_dir/wp-content/.whp"
    cs_target="$cs_dir/whp-magic-login-create.php"
    mkdir -p "$cs_dir"
    chown "$owner_uid:$owner_gid" "$cs_dir" 2>/dev/null || true
    if [ ! -f "$cs_dir/.htaccess" ]; then
        printf 'Require all denied\n' > "$cs_dir/.htaccess"
        chown "$owner_uid:$owner_gid" "$cs_dir/.htaccess"
        chmod 0644 "$cs_dir/.htaccess"
    fi

    if [ -f "$cs_target" ]; then
        cur_hash="$(sha256sum "$cs_target" | awk '{print $1}')"
        if [ "$cur_hash" = "$SRC_CRHASH" ]; then
            count_cs_already=$((count_cs_already+1))
        else
            install -m 0640 -o "$owner_uid" -g "$owner_gid" "$SRC_CREATESCRIPT" "$cs_target"
            count_cs_dropped=$((count_cs_dropped+1))
            echo "UPDATED create-script: $domain"
        fi
    else
        install -m 0640 -o "$owner_uid" -g "$owner_gid" "$SRC_CREATESCRIPT" "$cs_target"
        count_cs_dropped=$((count_cs_dropped+1))
        echo "INSTALLED create-script: $domain"
    fi

    # NOTE: we deliberately don't touch ~/.wp-cli/packages/. See the long
    # comment at the top of this file for why — short version: removing the
    # vendor dir while composer.json still references the package fatals
    # every subsequent wp-cli call on that site.
done <<< "$sites_tsv"

cat <<EOF

=== WHP magic-login backfill summary ===
sites in whp.wordpress_sites : $count_total
host dir missing (skipped)   : $count_no_dir
no wp-load.php (skipped)     : $count_no_wp
mu-plugin already patched    : $count_mu_already
mu-plugin patched/installed  : $count_mu_replaced
mu-plugin foreign (skipped)  : $count_mu_unrecognized
create-script up-to-date     : $count_cs_already
create-script dropped        : $count_cs_dropped
EOF

exit 0
