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

readonly SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
readonly PLUGIN_DIR="$(cd -- "${SCRIPT_DIR}/../.." && pwd)"
readonly ADMIN_DIR="${PLUGIN_DIR}/admin"
readonly FIXTURE="${SCRIPT_DIR}/fixtures/acf-field-table-fixture.php"
# shellcheck source=e2e-snapshot-contract.sh
source "${SCRIPT_DIR}/e2e-snapshot-contract.sh"

run_id_source="${IPZ_E2E_RUN_ID:-pid-$$}"
RUN_ID="$(printf '%s' "${run_id_source}" | tr '[:upper:]' '[:lower:]' | tr -cs 'a-z0-9_.-' '-')"
RUN_ID="${RUN_ID#-}"
RUN_ID="${RUN_ID%-}"
[[ -n "${RUN_ID}" ]] || {
    printf 'IPZ_E2E_RUN_ID must contain at least one ASCII letter or digit.\n' >&2
    exit 1
}
readonly RUN_ID
readonly LOCK_FILE="${TMPDIR:-/tmp}/ipz-e2e-$(id -u)-8080.lock"
readonly OWNERSHIP_LABEL="io.presszone.ipz-e2e.run=${RUN_ID}"
readonly NETWORK="acf-table-e2e-network-${RUN_ID}"
readonly DATABASE_CONTAINER="acf-table-e2e-database-${RUN_ID}"
readonly WORDPRESS_CONTAINER="acf-table-e2e-wordpress-${RUN_ID}"
readonly DATABASE_VOLUME="acf-table-e2e-database-data-${RUN_ID}"
readonly WORDPRESS_VOLUME="acf-table-e2e-wordpress-data-${RUN_ID}"
readonly MARIADB_IMAGE="${IPZ_MARIADB_IMAGE}"
readonly WORDPRESS_IMAGE="${IPZ_WORDPRESS_IMAGE}"
readonly WORDPRESS_CLI_IMAGE="${IPZ_WORDPRESS_CLI_IMAGE}"
readonly DATABASE_NAME="wordpress"
readonly DATABASE_USER="wordpress"
readonly DATABASE_PASSWORD="wordpress"
readonly ADMIN_USER="admin"
readonly ADMIN_PASSWORD="admin123"
readonly SITE_URL="http://127.0.0.1:8080"

require_command() {
    command -v "$1" >/dev/null 2>&1 || {
        printf 'Required command is unavailable: %s\n' "$1" >&2
        exit 1
    }
}

assert_candidate_admin_assets() {
    local node_bin=$1 dist_dir manifest

    dist_dir=${2:-"${ADMIN_DIR}/dist"}
    manifest="${dist_dir}/asset-manifest.json"
    [[ -f "${manifest}" ]] || {
        printf 'Candidate admin manifest is missing after build: %s\n' "${manifest}" >&2
        return 1
    }

    "${node_bin}" - "${dist_dir}" "${manifest}" <<'NODE'
const fs = require('fs');
const path = require('path');
const [distDir, manifestPath] = process.argv.slice(2);
const fail = (message) => {
    console.error(message);
    process.exit(1);
};
let manifest;
let distReal;
try {
    manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
    distReal = fs.realpathSync(distDir);
} catch (error) {
    fail(`Candidate admin manifest or dist directory is invalid: ${error.message}`);
}
const isInsideDist = (realPath) => {
    const relative = path.relative(distReal, realPath);
    return relative !== '' && !relative.startsWith(`..${path.sep}`) && relative !== '..' && !path.isAbsolute(relative);
};
const validateAsset = (asset, pattern) => {
    if (typeof asset !== 'string' || !pattern.test(asset) || path.posix.isAbsolute(asset) || path.win32.isAbsolute(asset)) {
        fail(`Candidate admin asset has an unsafe path: ${String(asset)}`);
    }
    const candidate = path.resolve(distDir, asset);
    let stats;
    let realPath;
    try {
        stats = fs.lstatSync(candidate);
        realPath = fs.realpathSync(candidate);
    } catch (error) {
        fail(`Candidate admin asset is missing: ${asset}`);
    }
    if (!stats.isFile() || !isInsideDist(realPath) || fs.statSync(candidate).size === 0) {
        fail(`Candidate admin asset is not a nonempty regular file under dist: ${asset}`);
    }
    return path.posix.basename(asset, path.posix.extname(asset));
};
const requireAssets = (entrypoint, assetType, pattern) => {
    const entry = manifest[entrypoint];
    if (!entry || typeof entry !== 'object' || !Array.isArray(entry[assetType]) || entry[assetType].length === 0) {
        fail(`Candidate admin manifest lacks ${entrypoint} ${assetType} assets.`);
    }
    return entry[assetType].map((asset) => validateAsset(asset, pattern));
};
const requireScriptOrder = (entrypoint, terminal) => {
    const names = requireAssets(entrypoint, 'js', /^js\/[A-Za-z0-9._-]+\.js$/);
    if (names.length < 2 || names[0] !== 'runtime' || names[names.length - 1] !== terminal) {
        fail(`Candidate admin manifest ${entrypoint} scripts must start with runtime.js and end with ${terminal}.js.`);
    }
    if (new Set(names).size !== names.length) {
        fail(`Candidate admin manifest ${entrypoint} scripts must have unique enqueue handles.`);
    }
};
requireScriptOrder('main', 'main');
requireScriptOrder('editor', 'editor');
const editor = manifest.editor;
if (Object.prototype.hasOwnProperty.call(editor, 'css')) {
    if (!Array.isArray(editor.css)) {
        fail('Candidate admin manifest editor css assets must be an array.');
    }
    editor.css.forEach((asset) => validateAsset(asset, /^css\/[A-Za-z0-9._-]+\.css$/));
}
validateAsset('css/main.css', /^css\/main\.css$/);
NODE
}

install_e2e_dependencies() {
    local npm_bin=$1

    [[ -f "${SCRIPT_DIR}/package.json" && -f "${SCRIPT_DIR}/package-lock.json" ]] || {
        printf 'E2E package.json or package-lock.json is missing: %s\n' "${SCRIPT_DIR}" >&2
        return 1
    }

    (
        cd "${SCRIPT_DIR}"
        "${npm_bin}" ci --ignore-scripts --no-audit --no-fund
    )
}

build_candidate_admin_assets() {
    local npm_bin=$1 node_bin=$2

    [[ -f "${ADMIN_DIR}/package.json" && -f "${ADMIN_DIR}/package-lock.json" ]] || {
        printf 'Candidate admin package.json or package-lock.json is missing: %s\n' "${ADMIN_DIR}" >&2
        return 1
    }

    (
        cd "${ADMIN_DIR}"
        "${npm_bin}" ci
        "${npm_bin}" run build
    )
    assert_candidate_admin_assets "${node_bin}"
}

inventory_owned_resources() {
    local containers networks volumes

    if ! containers="$(podman ps --all --filter "label=${OWNERSHIP_LABEL}" --format '{{.Names}}')"; then
        printf 'Failed to inventory current-run containers for label %s.\n' "${OWNERSHIP_LABEL}" >&2
        return 1
    fi
    if ! networks="$(podman network ls --filter "label=${OWNERSHIP_LABEL}" --format '{{.Name}}')"; then
        printf 'Failed to inventory current-run networks for label %s.\n' "${OWNERSHIP_LABEL}" >&2
        return 1
    fi
    if ! volumes="$(podman volume ls --filter "label=${OWNERSHIP_LABEL}" --format '{{.Name}}')"; then
        printf 'Failed to inventory current-run volumes for label %s.\n' "${OWNERSHIP_LABEL}" >&2
        return 1
    fi

    printf '%s\037%s\037%s\n' "${containers}" "${networks}" "${volumes}"
}

resource_names() {
    local resource_type=$1 label_filter=${2:-}
    local -a filter=()

    [[ -z "${label_filter}" ]] || filter=(--filter "label=${label_filter}")
    case "${resource_type}" in
        container)
            podman ps --all "${filter[@]}" --format '{{.Names}}'
            ;;
        network)
            podman network ls "${filter[@]}" --format '{{.Name}}'
            ;;
        volume)
            podman volume ls "${filter[@]}" --format '{{.Name}}'
            ;;
        *)
            printf 'Unknown Podman resource type: %s\n' "${resource_type}" >&2
            return 1
            ;;
    esac
}

resource_name_exists() {
    local resource_type=$1 resource_name=$2 names

    if ! names="$(resource_names "${resource_type}")"; then
        printf 'Failed to inventory %s names before acquiring E2E ownership.\n' "${resource_type}" >&2
        return 1
    fi
    if printf '%s\n' "${names}" | grep --fixed-strings --line-regexp --quiet "${resource_name}"; then
        printf 'IPZ E2E ownership collision: existing %s named %s. No Podman resources were changed.\n' \
            "${resource_type}" "${resource_name}" >&2
        return 2
    fi
}

assert_ownership_available() {
    local inventory containers networks volumes

    if ! inventory="$(inventory_owned_resources)"; then
        printf 'Cannot verify requested E2E ownership namespace. No Podman resources were changed.\n' >&2
        return 1
    fi
    IFS=$'\037' read -r containers networks volumes <<<"${inventory}"
    if [[ -n "${containers}${networks}${volumes}" ]]; then
        printf 'IPZ E2E ownership collision for label %s: containers=[%s] networks=[%s] volumes=[%s]. No Podman resources were changed.\n' \
            "${OWNERSHIP_LABEL}" "${containers}" "${networks}" "${volumes}" >&2
        return 1
    fi

    resource_name_exists container "${DATABASE_CONTAINER}" || return $?
    resource_name_exists container "${WORDPRESS_CONTAINER}" || return $?
    resource_name_exists network "${NETWORK}" || return $?
    resource_name_exists volume "${DATABASE_VOLUME}" || return $?
    resource_name_exists volume "${WORDPRESS_VOLUME}" || return $?
}

remove_owned_resources() {
    local resource_type=$1 names resource
    shift

    if ! names="$(resource_names "${resource_type}" "${OWNERSHIP_LABEL}")"; then
        printf 'Failed to inventory current-run %s resources for removal.\n' "${resource_type}" >&2
        return 1
    fi
    while IFS= read -r resource; do
        [[ -z "${resource}" ]] && continue
        if ! podman "$@" "${resource}" >/dev/null; then
            printf 'Failed to remove current-run %s resource %s.\n' "${resource_type}" "${resource}" >&2
            return 1
        fi
    done <<<"${names}"
}

cleanup_resources() {
    local inventory containers networks volumes

    if ! inventory="$(inventory_owned_resources)"; then
        return 1
    fi
    IFS=$'\037' read -r containers networks volumes <<<"${inventory}"

    remove_owned_resources container rm --force || return 1
    remove_owned_resources network network rm || return 1
    remove_owned_resources volume volume rm || return 1

    if ! inventory="$(inventory_owned_resources)"; then
        return 1
    fi
    IFS=$'\037' read -r containers networks volumes <<<"${inventory}"
    if [[ -n "${containers}${networks}${volumes}" ]]; then
        printf 'Cleanup failed; current-run resources survive (label %s): containers=[%s] networks=[%s] volumes=[%s]\n' \
            "${OWNERSHIP_LABEL}" "${containers}" "${networks}" "${volumes}" >&2
        return 1
    fi
}

cleanup() {
    local status=$?
    trap - EXIT INT TERM
    if ! cleanup_resources; then
        status=1
    fi
    exit "${status}"
}

run_with_port_lock() {
    local status

    if flock --nonblock --close --conflict-exit-code 75 "${LOCK_FILE}" "${BASH}" -c \
        'source "$1"; shift; main "$@"' _ "$0" "$@"; then
        return 0
    else
        status=$?
    fi
    if [[ ${status} -eq 75 ]]; then
        printf 'IPZ E2E port 8080 is busy for UID %s; another run holds %s. No Podman resources were created.\n' \
            "$(id -u)" "${LOCK_FILE}" >&2
        return 1
    fi
    return "${status}"
}

wait_for_database() {
    # First-boot datadir initialization on a loaded host can exceed three
    # minutes; the TCP probe below only succeeds once the real server (not
    # the socket-only init server) accepts connections, so the window must
    # cover the full initialization, not just process start.
    local attempt
    for attempt in $(seq 1 180); do
        if podman run --rm --label "${OWNERSHIP_LABEL}" --network "${NETWORK}" "${MARIADB_IMAGE}" \
            mariadb-admin ping --host="${DATABASE_CONTAINER}" --user="${DATABASE_USER}" --password="${DATABASE_PASSWORD}" --silent >/dev/null 2>&1; then
            return 0
        fi
        sleep 2
    done

    printf 'MariaDB did not become ready.\n' >&2
    podman logs "${DATABASE_CONTAINER}" >&2 || true
    return 1
}

wait_for_wordpress_files() {
    local attempt
    for attempt in $(seq 1 60); do
        if podman exec "${WORDPRESS_CONTAINER}" test -f /var/www/html/wp-includes/version.php \
            && podman exec "${WORDPRESS_CONTAINER}" test -f /var/www/html/wp-config.php; then
            return 0
        fi
        sleep 1
    done

    printf 'WordPress core or generated wp-config.php was not initialized.\n' >&2
    podman logs "${WORDPRESS_CONTAINER}" >&2 || true
    return 1
}

wp() {
    podman run --rm --label "${OWNERSHIP_LABEL}" --user 0 --network "${NETWORK}" --volumes-from "${WORDPRESS_CONTAINER}" \
        --env "WORDPRESS_DB_HOST=${DATABASE_CONTAINER}" \
        --env "WORDPRESS_DB_NAME=${DATABASE_NAME}" \
        --env "WORDPRESS_DB_USER=${DATABASE_USER}" \
        --env "WORDPRESS_DB_PASSWORD=${DATABASE_PASSWORD}" \
        "${WORDPRESS_CLI_IMAGE}" wp "$@" --allow-root
}

wp_with_connect_fixture_env() {
    local -a fixture_env=()

    [[ -n "${IPZ_E2E_SITE_API_KEY:-}" ]] && fixture_env+=(--env IPZ_E2E_SITE_API_KEY)
    [[ -n "${IPZ_E2E_SITE_ID:-}" ]] && fixture_env+=(--env IPZ_E2E_SITE_ID)
    [[ -n "${IPZ_E2E_ACCOUNT_EMAIL:-}" ]] && fixture_env+=(--env IPZ_E2E_ACCOUNT_EMAIL)
    [[ -n "${IPZ_E2E_ACCOUNT_DISPLAY_NAME:-}" ]] && fixture_env+=(--env IPZ_E2E_ACCOUNT_DISPLAY_NAME)

    podman run --rm --label "${OWNERSHIP_LABEL}" --user 0 --network "${NETWORK}" --volumes-from "${WORDPRESS_CONTAINER}" \
        --env "WORDPRESS_DB_HOST=${DATABASE_CONTAINER}" \
        --env "WORDPRESS_DB_NAME=${DATABASE_NAME}" \
        --env "WORDPRESS_DB_USER=${DATABASE_USER}" \
        --env "WORDPRESS_DB_PASSWORD=${DATABASE_PASSWORD}" \
        "${fixture_env[@]}" \
        "${WORDPRESS_CLI_IMAGE}" wp "$@" --allow-root
}

configure_translation_api_base() {
    local api_url=${IPZ_E2E_TRANSLATION_API_URL:-} actual

    [[ -n "${api_url}" ]] || return 0
    case "${api_url}" in
        https://*|http://127.0.0.1:*|http://localhost:*|http://\[::1\]:*) ;;
        *)
            printf 'IPZ_E2E_TRANSLATION_API_URL must use HTTPS, or HTTP on a loopback host.\n' >&2
            return 1
            ;;
    esac

    api_url=${api_url%/}
    wp config set IPZ_API_BASE_URL "${api_url}" --type=constant --quiet
    actual="$(wp eval 'echo defined("IPZ_API_BASE_URL") ? rtrim((string) IPZ_API_BASE_URL, "/") : "";')"
    [[ "${actual}" == "${api_url}" ]] || {
        printf 'E2E translation API base was not applied.\n' >&2
        return 1
    }
}

provision_connect_credential() {
    local has_key=0 has_site_id=0

    [[ -n "${IPZ_E2E_SITE_API_KEY:-}" ]] && has_key=1
    [[ -n "${IPZ_E2E_SITE_ID:-}" ]] && has_site_id=1
    if ((has_key != has_site_id)); then
        printf 'IPZ_E2E_SITE_API_KEY and IPZ_E2E_SITE_ID must be supplied together.\n' >&2
        return 1
    fi
    ((has_key == 1)) || return 0

    wp_with_connect_fixture_env eval '
$api_key = getenv("IPZ_E2E_SITE_API_KEY");
$site_id = getenv("IPZ_E2E_SITE_ID");
$email = getenv("IPZ_E2E_ACCOUNT_EMAIL");
$display_name = getenv("IPZ_E2E_ACCOUNT_DISPLAY_NAME");
if (!is_string($api_key) || $api_key === "" || !is_string($site_id) || $site_id === "") {
    fwrite(STDERR, "E2E Connect credential environment is incomplete.\n");
    exit(1);
}
$store = new \InternationalPressZone\Connect\CredentialStore();
if (!$store->save($api_key, $site_id, array(
    "email" => is_string($email) ? $email : "",
    "display_name" => is_string($display_name) ? $display_name : "",
))) {
    fwrite(STDERR, "E2E Connect credential could not be stored.\n");
    exit(1);
}
$stored = $store->get_api_key();
if (!is_string($stored) || !hash_equals($api_key, $stored)) {
    fwrite(STDERR, "E2E Connect credential verification failed.\n");
    exit(1);
}
$metadata = $store->metadata();
if (($metadata["site_id"] ?? "") !== strtolower($site_id)) {
    fwrite(STDERR, "E2E Connect site metadata verification failed.\n");
    exit(1);
}
$service = new \InternationalPressZone\Connect\ConnectService($store);
$status = $service->status(true);
if (is_wp_error($status) || empty($status["connected"])) {
    $code = is_wp_error($status) ? $status->get_error_code() : "disconnected";
    fwrite(STDERR, "E2E Connect credential failed backend status verification: " . $code . "\n");
    exit(1);
}
'
    printf 'Connect E2E credential provisioned and backend-verified for site fixture (secret withheld).\n'
}

provision_pretty_permalinks() {
    local permalink_structure

    podman exec "${WORDPRESS_CONTAINER}" touch /var/www/html/.htaccess
    podman exec "${WORDPRESS_CONTAINER}" chown www-data:www-data /var/www/html/.htaccess
    podman exec "${WORDPRESS_CONTAINER}" chmod 664 /var/www/html/.htaccess
    wp rewrite structure '/%postname%/'
    wp rewrite flush
    wp eval '
global $wp_rewrite;
$rules = $wp_rewrite->mod_rewrite_rules();
if (!is_string($rules) || $rules === "") {
    fwrite(STDERR, "Apache rewrite rule generation failed.\\n");
    exit(1);
}
if (file_put_contents(ABSPATH . ".htaccess", $rules) === false) {
    fwrite(STDERR, "Apache .htaccess write failed.\\n");
    exit(1);
}
'
    podman exec "${WORDPRESS_CONTAINER}" chown www-data:www-data /var/www/html/.htaccess
    podman exec "${WORDPRESS_CONTAINER}" chmod 664 /var/www/html/.htaccess
    permalink_structure="$(wp option get permalink_structure)"
    [[ "${permalink_structure}" == '/%postname%/' ]] || {
        printf 'Pretty permalink provisioning failed: expected /%%postname%%/, got %s.\n' "${permalink_structure}" >&2
        return 1
    }
}

assert_rest_json_routing() {
    if podman exec "${WORDPRESS_CONTAINER}" php -r '
$url = "http://127.0.0.1/wp-json/";
$context = stream_context_create(array("http" => array("header" => "Host: 127.0.0.1:8080\r\n", "ignore_errors" => true, "timeout" => 5)));
$body = @file_get_contents($url, false, $context);
$headers = $http_response_header ?? array();
$content_type = "";
foreach ($headers as $header) {
    if (stripos($header, "Content-Type:") === 0) {
        $content_type = trim(substr($header, strlen("Content-Type:")));
        break;
    }
}
if (!is_string($body) || stripos($content_type, "application/json") !== 0 || json_decode($body, true) === null) {
    fwrite(STDERR, sprintf("REST rewrite smoke failed: /wp-json/ content-type=%s body-prefix=%s\\n", $content_type ?: "missing", is_string($body) ? substr($body, 0, 80) : "unavailable"));
    exit(1);
}
'; then
        return 0
    fi

    printf 'REST rewrite smoke failed: /wp-json/ did not return JSON before port publication.\n' >&2
    return 1
}

assert_acf_fixture_graph() {
    wp eval '
$required_fields = array(
    "field_acf_table_e2e_intro" => "text",
    "field_acf_table_e2e_repeater" => "repeater",
    "field_acf_table_e2e_repeater_title" => "text",
    "field_acf_table_e2e_repeater_copy" => "textarea",
    "field_acf_table_e2e_flexible" => "flexible_content",
    "field_acf_table_e2e_hero_heading" => "text",
    "field_acf_table_e2e_hero_items" => "repeater",
    "field_acf_table_e2e_hero_item_label" => "text",
    "field_acf_table_e2e_callout_message" => "textarea",
    "field_acf_table_e2e_secondary_note" => "textarea",
);
foreach ($required_fields as $key => $type) {
    $field = acf_get_field($key);
    if (!is_array($field) || $field["key"] !== $key || $field["type"] !== $type) {
        fwrite(STDERR, sprintf("ACF fixture field assertion failed: %s\\n", $key));
        exit(1);
    }
}
$field_keys = static function ($fields): array {
    $keys = array();
    foreach ((array) $fields as $field) {
        if (is_array($field) && isset($field["key"])) {
            $keys[] = $field["key"];
        }
    }
    return $keys;
};
$assert_child_keys = static function ($fields, array $expected, string $parent) use ($field_keys): void {
    if ($field_keys($fields) !== $expected) {
        fwrite(STDERR, sprintf("ACF fixture child graph assertion failed: %s\\n", $parent));
        exit(1);
    }
};
$repeater = acf_get_field("field_acf_table_e2e_repeater");
$assert_child_keys($repeater["sub_fields"] ?? array(), array("field_acf_table_e2e_repeater_title", "field_acf_table_e2e_repeater_copy"), $repeater["key"]);
$hero_items = acf_get_field("field_acf_table_e2e_hero_items");
$assert_child_keys($hero_items["sub_fields"] ?? array(), array("field_acf_table_e2e_hero_item_label"), $hero_items["key"]);
$flexible = acf_get_field("field_acf_table_e2e_flexible");
$layouts = array();
foreach ((array) $flexible["layouts"] as $layout) {
    if (is_array($layout) && isset($layout["key"])) {
        $layouts[$layout["key"]] = $layout;
    }
}
foreach (array("layout_acf_table_e2e_hero", "layout_acf_table_e2e_callout") as $key) {
    if (!isset($layouts[$key]) || $layouts[$key]["key"] !== $key) {
        fwrite(STDERR, sprintf("ACF fixture layout assertion failed: %s\\n", $key));
        exit(1);
    }
}
$assert_child_keys($layouts["layout_acf_table_e2e_hero"]["sub_fields"] ?? array(), array("field_acf_table_e2e_hero_heading", "field_acf_table_e2e_hero_items"), "layout_acf_table_e2e_hero");
$assert_child_keys($layouts["layout_acf_table_e2e_callout"]["sub_fields"] ?? array(), array("field_acf_table_e2e_callout_message"), "layout_acf_table_e2e_callout");
'
}

run_candidate_admin_asset_tests() {
    local node_bin

    node_bin="$(command -v node)"
    [[ "${node_bin}" == /* && -x "${node_bin}" ]] || {
        printf 'Self-test requires an executable absolute node path: %s\n' "${node_bin}" >&2
        return 1
    }

    (
        local workspace
        workspace="$(mktemp -d)"
        trap 'rm -rf -- "${workspace}"' EXIT

        prepare_fixture() {
            local directory=$1 manifest=$2

            mkdir -p "${directory}/js" "${directory}/css"
            printf 'runtime' >"${directory}/js/runtime.js"
            printf 'chunk' >"${directory}/js/512.chunk.js"
            printf 'chunk' >"${directory}/js/101.chunk.js"
            printf 'main' >"${directory}/js/main.js"
            printf 'editor' >"${directory}/js/editor.js"
            printf 'editor css' >"${directory}/css/editor.css"
            printf 'main css' >"${directory}/css/main.css"
            printf '%s\n' "${manifest}" >"${directory}/asset-manifest.json"
        }

        assert_rejected_fixture() {
            local name=$1 directory=$2

            if assert_candidate_admin_assets "${node_bin}" "${directory}" >/dev/null 2>&1; then
                printf 'Candidate admin asset self-test accepted invalid %s fixture.\n' "${name}" >&2
                exit 1
            fi
        }

        valid_manifest='{"main":{"js":["js/runtime.js","js/512.chunk.js","js/101.chunk.js","js/main.js"]},"editor":{"js":["js/runtime.js","js/101.chunk.js","js/512.chunk.js","js/editor.js"],"css":["css/editor.css"]}}'
        prepare_fixture "${workspace}/pass" "${valid_manifest}"
        assert_candidate_admin_assets "${node_bin}" "${workspace}/pass" || {
            printf 'Candidate admin asset self-test rejected valid fixture.\n' >&2
            exit 1
        }

        prepare_fixture "${workspace}/editor-only" '{"main":{"js":["js/runtime.js","js/main.js"]},"editor":{"js":["js/editor.js"]}}'
        assert_rejected_fixture 'editor-only' "${workspace}/editor-only"

        prepare_fixture "${workspace}/main-before-runtime" '{"main":{"js":["js/main.js","js/runtime.js"]},"editor":{"js":["js/runtime.js","js/editor.js"]}}'
        assert_rejected_fixture 'main-before-runtime' "${workspace}/main-before-runtime"

        prepare_fixture "${workspace}/editor-before-runtime" '{"main":{"js":["js/runtime.js","js/main.js"]},"editor":{"js":["js/editor.js","js/runtime.js"]}}'
        assert_rejected_fixture 'editor-before-runtime' "${workspace}/editor-before-runtime"

        prepare_fixture "${workspace}/runtime-terminal" '{"main":{"js":["js/runtime.js","js/main.js","js/runtime.js"]},"editor":{"js":["js/runtime.js","js/editor.js"]}}'
        assert_rejected_fixture 'runtime duplicated in terminal position' "${workspace}/runtime-terminal"

        prepare_fixture "${workspace}/runtime-middle" '{"main":{"js":["js/runtime.js","js/runtime.js","js/512.chunk.js","js/main.js"]},"editor":{"js":["js/runtime.js","js/editor.js"]}}'
        assert_rejected_fixture 'runtime duplicated in middle position' "${workspace}/runtime-middle"

        prepare_fixture "${workspace}/chunk-adjacent" '{"main":{"js":["js/runtime.js","js/512.chunk.js","js/512.chunk.js","js/main.js"]},"editor":{"js":["js/runtime.js","js/editor.js"]}}'
        assert_rejected_fixture 'adjacent duplicate chunk' "${workspace}/chunk-adjacent"

        prepare_fixture "${workspace}/chunk-nonadjacent" '{"main":{"js":["js/runtime.js","js/512.chunk.js","js/101.chunk.js","js/512.chunk.js","js/main.js"]},"editor":{"js":["js/runtime.js","js/editor.js"]}}'
        assert_rejected_fixture 'nonadjacent duplicate chunk' "${workspace}/chunk-nonadjacent"

        prepare_fixture "${workspace}/non-js-entry" '{"main":{"js":["js/runtime.js","css/editor.css","js/main.js"]},"editor":{"js":["js/runtime.js","js/editor.js"]}}'
        assert_rejected_fixture 'non-js entry' "${workspace}/non-js-entry"

        prepare_fixture "${workspace}/terminal-drift" '{"main":{"js":["js/runtime.js","js/main.js"]},"editor":{"js":["js/runtime.js","js/512.chunk.js"]}}'
        assert_rejected_fixture 'terminal drift' "${workspace}/terminal-drift"

        prepare_fixture "${workspace}/missing-hardcoded-css" "${valid_manifest}"
        rm "${workspace}/missing-hardcoded-css/css/main.css"
        assert_rejected_fixture 'missing hardcoded CSS' "${workspace}/missing-hardcoded-css"

        prepare_fixture "${workspace}/traversal" '{"main":{"js":["js/../runtime.js","js/main.js"]},"editor":{"js":["js/runtime.js","js/editor.js"]}}'
        assert_rejected_fixture 'traversal' "${workspace}/traversal"

        prepare_fixture "${workspace}/absent-file" '{"main":{"js":["js/runtime.js","js/main.js"]},"editor":{"js":["js/runtime.js","js/missing.js","js/editor.js"]}}'
        assert_rejected_fixture 'absent file' "${workspace}/absent-file"

        prepare_fixture "${workspace}/empty-file" "${valid_manifest}"
        : >"${workspace}/empty-file/js/editor.js"
        assert_rejected_fixture 'empty file' "${workspace}/empty-file"
    )
}

run_port_lock_self_test() (
    local workspace lock_file child_pid

    workspace="$(mktemp -d)"
    lock_file="${workspace}/port.lock"
    trap '[[ -z "${child_pid:-}" ]] || kill "${child_pid}" >/dev/null 2>&1 || true; rm -rf -- "${workspace}"' EXIT

    flock --nonblock --close "${lock_file}" bash -c 'sleep 30 & printf "%s\n" "$!" >"$1"; disown' _ "${workspace}/child.pid"
    child_pid="$(<"${workspace}/child.pid")"
    kill -0 "${child_pid}" >/dev/null 2>&1 || {
        printf 'Port-lock self-test did not leave a live descendant.\n' >&2
        return 1
    }
    if ! flock --nonblock "${lock_file}" true; then
        printf 'Port-lock self-test found the lock inherited by a descendant.\n' >&2
        return 1
    fi
)

run_mocked_tests() {
    run_candidate_admin_asset_tests
    run_port_lock_self_test

    (
        podman() { return 77; }
        if cleanup_resources >/dev/null 2>&1; then
            printf 'Mocked inventory failure incorrectly succeeded.\n' >&2
            exit 1
        fi
    )
    (
        log="$(mktemp)"
        trap 'rm -f -- "${log}"' EXIT
        owned_container=1
        owned_network=1
        owned_volume=1
        podman() {
            local filter= argument
            case "$1" in
                ps)
                    shift
                    while (($#)); do
                        argument=$1
                        shift
                        [[ "${argument}" == '--filter' && $# -gt 0 ]] && {
                            filter=$1
                            shift
                        }
                    done
                    printf 'inventory container %s\n' "${filter}" >>"${log}"
                    if [[ "${filter}" == "label=${OWNERSHIP_LABEL}" && ${owned_container} -eq 1 ]]; then
                        printf 'owned-container\n'
                    elif [[ "${filter}" == "label=${RUN_ID}" ]]; then
                        printf 'foreign-container\n'
                    fi
                    ;;
                network)
                    if [[ "${2:-}" == 'ls' ]]; then
                        shift 2
                        while (($#)); do
                            argument=$1
                            shift
                            [[ "${argument}" == '--filter' && $# -gt 0 ]] && {
                                filter=$1
                                shift
                            }
                        done
                        printf 'inventory network %s\n' "${filter}" >>"${log}"
                        if [[ "${filter}" == "label=${OWNERSHIP_LABEL}" && ${owned_network} -eq 1 ]]; then
                            printf 'owned-network\n'
                        elif [[ "${filter}" == "label=${RUN_ID}" ]]; then
                            printf 'foreign-network\n'
                        fi
                    elif [[ "${2:-}" == 'rm' ]]; then
                        printf 'remove network %s\n' "${3:-}" >>"${log}"
                        [[ "${3:-}" == 'owned-network' ]] && owned_network=0
                    fi
                    ;;
                volume)
                    if [[ "${2:-}" == 'ls' ]]; then
                        shift 2
                        while (($#)); do
                            argument=$1
                            shift
                            [[ "${argument}" == '--filter' && $# -gt 0 ]] && {
                                filter=$1
                                shift
                            }
                        done
                        printf 'inventory volume %s\n' "${filter}" >>"${log}"
                        if [[ "${filter}" == "label=${OWNERSHIP_LABEL}" && ${owned_volume} -eq 1 ]]; then
                            printf 'owned-volume\n'
                        elif [[ "${filter}" == "label=${RUN_ID}" ]]; then
                            printf 'foreign-volume\n'
                        fi
                    elif [[ "${2:-}" == 'rm' ]]; then
                        printf 'remove volume %s\n' "${3:-}" >>"${log}"
                        [[ "${3:-}" == 'owned-volume' ]] && owned_volume=0
                    fi
                    ;;
                rm)
                    printf 'remove container %s\n' "${3:-}" >>"${log}"
                    [[ "${3:-}" == 'owned-container' ]] && owned_container=0
                    ;;
            esac
        }
        cleanup_resources >/dev/null || {
            printf 'Mocked exact-label cleanup failed.\n' >&2
            exit 1
        }
        for resource_type in container network volume; do
            [[ "$(grep --fixed-strings --line-regexp --count "inventory ${resource_type} label=${OWNERSHIP_LABEL}" "${log}")" -eq 3 ]] || {
                printf 'Mocked %s inventory did not use exact ownership label.\n' "${resource_type}" >&2
                exit 1
            }
            grep --fixed-strings --line-regexp --quiet "remove ${resource_type} owned-${resource_type}" "${log}" || {
                printf 'Mocked owned %s was not removed.\n' "${resource_type}" >&2
                exit 1
            }
        done
        if grep --fixed-strings --quiet 'foreign-' "${log}"; then
            printf 'Mocked foreign bare-run-ID resource was selected.\n' >&2
            exit 1
        fi
    )
    (
        local deleted=0
        podman() {
            if [[ "$1" == 'rm' || ( "$1" == 'network' && "${2:-}" == 'rm' ) || ( "$1" == 'volume' && "${2:-}" == 'rm' ) ]]; then
                deleted=1
            fi
            if [[ "$1" == 'info' ]]; then
                return 0
            fi
            if [[ "$1" == 'ps' ]]; then
                printf 'existing-owned-container\n'
            fi
            return 0
        }
        require_command() { :; }
        build_candidate_admin_assets() { :; }
        if main >/dev/null 2>&1; then
            printf 'Mocked reused-ID collision incorrectly succeeded.\n' >&2
            exit 1
        fi
        [[ -z "$(trap -p EXIT)" && "${deleted}" -eq 0 ]] || {
            printf 'Mocked reused-ID collision installed cleanup or deleted resources.\n' >&2
            exit 1
        }
    )
    (
        log="$(mktemp)"
        trap 'rm -f -- "${log}"' EXIT
        podman() {
            printf 'podman %s\n' "$*" >>"${log}"
        }
        wp() {
            if [[ "$*" == 'option get permalink_structure' ]]; then
                printf '/%%postname%%/\n'
            else
                printf 'wp %s\n' "$*" >>"${log}"
            fi
        }
        provision_pretty_permalinks
        grep --fixed-strings --quiet 'podman exec acf-table-e2e-wordpress-' "${log}" || {
            printf 'Mocked permalink provisioning did not prepare the WordPress container.\n' >&2
            exit 1
        }
        grep --fixed-strings --line-regexp --quiet 'wp rewrite structure /%postname%/' "${log}" || {
            printf 'Mocked permalink provisioning did not set postname structure.\n' >&2
            exit 1
        }
        grep --fixed-strings --line-regexp --quiet 'wp rewrite flush' "${log}" || {
            printf 'Mocked permalink provisioning did not flush rewrite rules.\n' >&2
            exit 1
        }
        grep --fixed-strings --quiet 'wp eval ' "${log}" || {
            printf 'Mocked permalink provisioning did not write Apache rewrite rules.\n' >&2
            exit 1
        }
    )
    (
        log="$(mktemp)"
        trap 'rm -f -- "${log}"' EXIT
        export IPZ_E2E_TRANSLATION_API_URL='https://worker.example.test/'
        wp() {
            if [[ "${1:-}" == 'eval' ]]; then
                printf 'https://worker.example.test'
            else
                printf 'wp %s\n' "$*" >>"${log}"
            fi
        }
        configure_translation_api_base
        grep --fixed-strings --line-regexp --quiet 'wp config set IPZ_API_BASE_URL https://worker.example.test --type=constant --quiet' "${log}" || {
            printf 'Mocked translation API base provisioning did not write the expected constant.\n' >&2
            exit 1
        }
        export IPZ_E2E_TRANSLATION_API_URL='http://worker.example.test:8787'
        if configure_translation_api_base >/dev/null 2>&1; then
            printf 'Mocked unsafe HTTP translation API base incorrectly succeeded.\n' >&2
            exit 1
        fi
    )
    (
        unset IPZ_E2E_SITE_API_KEY IPZ_E2E_SITE_ID IPZ_E2E_ACCOUNT_EMAIL IPZ_E2E_ACCOUNT_DISPLAY_NAME
        podman() {
            printf 'Credential provisioning unexpectedly invoked podman without a fixture.\n' >&2
            return 1
        }
        provision_connect_credential
        export IPZ_E2E_SITE_API_KEY='fixture-secret-must-not-appear'
        if provision_connect_credential >/dev/null 2>&1; then
            printf 'Mocked incomplete Connect credential fixture incorrectly succeeded.\n' >&2
            exit 1
        fi
        export IPZ_E2E_SITE_ID='00000000-0000-4000-8000-000000000001'
        log="$(mktemp)"
        trap 'rm -f -- "${log}"' EXIT
        podman() {
            printf '%s\n' "$*" >>"${log}"
        }
        provision_connect_credential >/dev/null
        grep --fixed-strings --quiet -- '--env IPZ_E2E_SITE_API_KEY' "${log}" || {
            printf 'Mocked Connect fixture did not forward the API-key environment by name.\n' >&2
            exit 1
        }
        grep --fixed-strings --quiet -- '--env IPZ_E2E_SITE_ID' "${log}" || {
            printf 'Mocked Connect fixture did not forward the site-ID environment by name.\n' >&2
            exit 1
        }
        if grep --fixed-strings --quiet 'fixture-secret-must-not-appear' "${log}"; then
            printf 'Mocked Connect fixture exposed the API key in the container argv.\n' >&2
            exit 1
        fi
    )
}

start_wordpress_container() {
    local exposure=$1
    local -a publish=()
    [[ "${exposure}" == 'published' ]] && publish=(--publish 127.0.0.1:8080:80)

    podman run --detach --name "${WORDPRESS_CONTAINER}" --label "${OWNERSHIP_LABEL}" --network "${NETWORK}" \
        "${publish[@]}" \
        --volume "${WORDPRESS_VOLUME}:/var/www/html:Z" \
        --volume "${PLUGIN_DIR}:/var/www/html/wp-content/plugins/international-press-zone:ro,Z" \
        --env "WORDPRESS_DB_HOST=${DATABASE_CONTAINER}" --env "WORDPRESS_DB_NAME=${DATABASE_NAME}" \
        --env "WORDPRESS_DB_USER=${DATABASE_USER}" --env "WORDPRESS_DB_PASSWORD=${DATABASE_PASSWORD}" \
        "${WORDPRESS_IMAGE}" >/dev/null
}

main() {
local npm_bin node_bin

require_command podman
require_command flock
require_command npm
require_command node
npm_bin="$(command -v npm)"
node_bin="$(command -v node)"
[[ "${npm_bin}" == /* && "${node_bin}" == /* ]] || {
    printf 'Resolved npm/node entrypoints must be absolute: npm=%s node=%s\n' "${npm_bin}" "${node_bin}" >&2
    exit 1
}
[[ -x "${npm_bin}" && -x "${node_bin}" ]] || {
    printf 'Resolved npm/node entrypoint is not executable: npm=%s node=%s\n' "${npm_bin}" "${node_bin}" >&2
    exit 1
}
[[ -f "${PLUGIN_DIR}/international-press-zone.php" ]] || {
    printf 'Candidate plugin entrypoint is missing: %s\n' "${PLUGIN_DIR}/international-press-zone.php" >&2
    exit 1
}
[[ -f "${FIXTURE}" ]] || {
    printf 'ACF fixture is missing: %s\n' "${FIXTURE}" >&2
    exit 1
}
install_e2e_dependencies "${npm_bin}"
build_candidate_admin_assets "${npm_bin}" "${node_bin}"

podman info >/dev/null
assert_ownership_available || return 1
trap cleanup EXIT INT TERM

snapshot_dir="$(ipz_snapshot_dir)"
ipz_validate_snapshot "${snapshot_dir}"
podman network create --label "${OWNERSHIP_LABEL}" "${NETWORK}" >/dev/null
podman volume create --label "${OWNERSHIP_LABEL}" "${DATABASE_VOLUME}" >/dev/null
podman volume create --label "${OWNERSHIP_LABEL}" "${WORDPRESS_VOLUME}" >/dev/null
podman run --rm --label "${OWNERSHIP_LABEL}" --volume "${DATABASE_VOLUME}:/restore:Z" --volume "${snapshot_dir}:/snapshot:ro,Z" \
    docker.io/library/alpine:3.20 tar -C /restore -xf /snapshot/database.tar
podman run --rm --label "${OWNERSHIP_LABEL}" --volume "${WORDPRESS_VOLUME}:/restore:Z" --volume "${snapshot_dir}:/snapshot:ro,Z" \
    docker.io/library/alpine:3.20 tar -C /restore -xf /snapshot/wordpress.tar

podman run --detach --name "${DATABASE_CONTAINER}" --label "${OWNERSHIP_LABEL}" --network "${NETWORK}" \
    --volume "${DATABASE_VOLUME}:/var/lib/mysql:Z" \
    --env "MARIADB_DATABASE=${DATABASE_NAME}" --env "MARIADB_USER=${DATABASE_USER}" \
    --env "MARIADB_PASSWORD=${DATABASE_PASSWORD}" --env "MARIADB_ROOT_PASSWORD=${DATABASE_PASSWORD}" \
    "${MARIADB_IMAGE}" >/dev/null
wait_for_database

start_wordpress_container private
wait_for_wordpress_files
configure_translation_api_base
wp core is-installed
wp user set-role "${ADMIN_USER}" administrator
wp cache flush
wp eval '$user = get_user_by("login", "admin"); if (!$user || !$user->has_cap("manage_options")) { fwrite(STDERR, "E2E administrator lacks manage_options.\n"); exit(1); }'
wp plugin activate international-press-zone
wp plugin is-active advanced-custom-fields
wp plugin is-active international-press-zone
provision_connect_credential
assert_acf_fixture_graph
assert_rest_json_routing

podman stop "${WORDPRESS_CONTAINER}" >/dev/null
podman rm "${WORDPRESS_CONTAINER}" >/dev/null
start_wordpress_container published

printf 'ACF table E2E stack ready at %s (run %s)\n' "${SITE_URL}" "${RUN_ID}"
podman wait "${WORDPRESS_CONTAINER}" >/dev/null
}

if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
    if [[ "${1:-}" == '--self-test' ]]; then
        run_mocked_tests
    else
        run_with_port_lock "$@"
    fi
fi
