#!/usr/bin/env bash
# shellcheck disable=SC2016
set -euo pipefail

SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
readonly SCRIPT_DIR
readonly RUNNER="${SCRIPT_DIR}/run-remote.sh"
WORKSPACE="$(mktemp -d)"
readonly WORKSPACE
trap 'rm -rf -- "${WORKSPACE}"' EXIT

fail() {
    printf 'FAIL: %s\n' "$1" >&2
    exit 1
}

make_transport() {
    local destination="$1"
    cat >"${destination}" <<'MOCK'
#!/usr/bin/env bash
set -euo pipefail
if [[ -n "${IPZ_TEST_CWD_LOG:-}" ]]; then
    pwd >"${IPZ_TEST_CWD_LOG}"
fi
printf '%s\0' "$@" >"${IPZ_TEST_ARGV_LOG}"
client_index=0
for argument in "$@"; do
    client_index=$((client_index + 1))
    [[ "${argument}" == '--' ]] && break
done
shift "${client_index}"
"$@"
MOCK
    chmod +x "${destination}"
}

assert_sequence() {
    local log="$1"
    local expected=$'1|test universal-admin-component-redesign.spec.js --project=chromium\n2|test universal-admin-component-redesign.spec.js --project=chromium\n3|test universal-admin-component-redesign.spec.js --project=chromium\nFINAL|test universal-admin-assertions.spec.js --project=chromium\nFINAL|test fields-table-overflow.spec.js --project=chromium\nFINAL|test universal-admin-component-redesign.spec.js --project=chromium\n'
    [[ "$(<"${log}")"$'\n' == "${expected}" ]] || fail "unexpected pass sequence"
    [[ "$(grep -c 'universal-admin-assertions.spec.js' "${log}")" -eq 1 ]] || fail 'assertion spec must run exactly once'
    [[ "$(grep -c 'fields-table-overflow.spec.js' "${log}")" -eq 1 ]] || fail 'Fields overflow spec must run exactly once'
    [[ "$(grep 'universal-admin-assertions.spec.js' "${log}")" == 'FINAL|test universal-admin-assertions.spec.js --project=chromium' ]] || fail 'assertion spec must not run as a calibration capture'
    [[ "$(grep 'fields-table-overflow.spec.js' "${log}")" == 'FINAL|test fields-table-overflow.spec.js --project=chromium' ]] || fail 'Fields overflow spec must run after calibration'
}

run_success_test() {
    local root="${WORKSPACE}/repo root with spaces"
    local plugin="${root}/nested plugins/plugin with spaces"
    local mock="${WORKSPACE}/mock transport"
    local argv_log="${WORKSPACE}/argv"
    local sequence_log="${WORKSPACE}/sequence"
    git init -q "${root}"
    mkdir -p "${plugin}/tests/e2e"
    cp "${RUNNER}" "${plugin}/tests/e2e/run-remote.sh"
    cp "${SCRIPT_DIR}/run-remote-client.sh" "${plugin}/tests/e2e/run-remote-client.sh"
    : >"${plugin}/tests/e2e/remote-stack.sh"
    : >"${plugin}/tests/e2e/package-lock.json"
    cat >"${plugin}/tests/e2e/run-playwright.sh" <<'PLAYWRIGHT'
#!/usr/bin/env bash
set -euo pipefail
printf '%s|%s\n' "${IPZ_VISUAL_CALIBRATION_RUN:-FINAL}" "$*" >>"${IPZ_TEST_SEQUENCE_LOG}"
PLAYWRIGHT
    chmod +x "${plugin}/tests/e2e/"*.sh
    make_transport "${mock}"

    local cwd_log="${WORKSPACE}/cwd"
    IPZ_TEST_CWD_LOG="${cwd_log}" \
        IPZ_RUN_REMOTE_TEST_MODE=1 IPZ_E2E_REMOTE_BIN="${mock}" IPZ_TEST_ARGV_LOG="${argv_log}" \
        IPZ_TEST_SEQUENCE_LOG="${sequence_log}" "${plugin}/tests/e2e/run-remote.sh"

    [[ "$(<"${cwd_log}")" == "${plugin}/tests/e2e" ]] || fail 'transport must run from the nested E2E package'
    [[ -f "${plugin}/tests/e2e/package-lock.json" ]] || fail 'nested package lockfile is missing'

    assert_sequence "${sequence_log}"
    mapfile -d '' -t argv <"${argv_log}"
    local expected=(
        --server './remote-stack.sh' --wait-port 8080 --wait-sec 600
        --env 'WP_BASE_URL=http://127.0.0.1:8080'
        --mkdir '../../tests/artifacts/universal-admin'
        --mkdir '../../tests/artifacts/universal-admin/calibration/run-1'
        --mkdir '../../tests/artifacts/universal-admin/calibration/run-2'
        --mkdir '../../tests/artifacts/universal-admin/calibration/run-3'
        --
        './run-remote-client.sh'
    )
    [[ "${#argv[@]}" -eq "${#expected[@]}" ]] || fail "unexpected transport argument count"
    local index
    for index in "${!expected[@]}"; do
        [[ "${argv[index]}" == "${expected[index]}" ]] || fail "transport argument ${index} differs"
    done
}

run_fail_fast_test() {
    local root="${WORKSPACE}/failure repo"
    local mock="${WORKSPACE}/failure transport"
    local sequence_log="${WORKSPACE}/failure sequence"
    git init -q "${root}"
    mkdir -p "${root}/tests/e2e"
    cp "${RUNNER}" "${root}/tests/e2e/run-remote.sh"
    cp "${SCRIPT_DIR}/run-remote-client.sh" "${root}/tests/e2e/run-remote-client.sh"
    : >"${root}/tests/e2e/remote-stack.sh"
    cat >"${root}/tests/e2e/run-playwright.sh" <<'PLAYWRIGHT'
#!/usr/bin/env bash
set -euo pipefail
value="${IPZ_VISUAL_CALIBRATION_RUN:-FINAL}"
printf '%s\n' "${value}" >>"${IPZ_TEST_SEQUENCE_LOG}"
[[ "${value}" != 2 ]]
PLAYWRIGHT
    chmod +x "${root}/tests/e2e/"*.sh
    make_transport "${mock}"

    if IPZ_RUN_REMOTE_TEST_MODE=1 IPZ_E2E_REMOTE_BIN="${mock}" IPZ_TEST_ARGV_LOG="${WORKSPACE}/failure argv" \
        IPZ_TEST_SEQUENCE_LOG="${sequence_log}" "${root}/tests/e2e/run-remote.sh"; then
        fail 'runner ignored failed calibration pass'
    fi
    [[ "$(<"${sequence_log}")"$'\n' == $'1\n2\n' ]] || fail 'runner did not stop on first failure'
}

run_fields_overflow_fail_fast_test() {
    local root="${WORKSPACE}/fields overflow failure repo"
    local mock="${WORKSPACE}/fields overflow failure transport"
    local sequence_log="${WORKSPACE}/fields overflow failure sequence"
    git init -q "${root}"
    mkdir -p "${root}/tests/e2e"
    cp "${RUNNER}" "${root}/tests/e2e/run-remote.sh"
    cp "${SCRIPT_DIR}/run-remote-client.sh" "${root}/tests/e2e/run-remote-client.sh"
    : >"${root}/tests/e2e/remote-stack.sh"
    cat >"${root}/tests/e2e/run-playwright.sh" <<'PLAYWRIGHT'
#!/usr/bin/env bash
set -euo pipefail
printf '%s|%s\n' "${IPZ_VISUAL_CALIBRATION_RUN:-FINAL}" "$*" >>"${IPZ_TEST_SEQUENCE_LOG}"
[[ "$*" != *'fields-table-overflow.spec.js'* ]]
PLAYWRIGHT
    chmod +x "${root}/tests/e2e/"*.sh
    make_transport "${mock}"

    if IPZ_RUN_REMOTE_TEST_MODE=1 IPZ_E2E_REMOTE_BIN="${mock}" IPZ_TEST_ARGV_LOG="${WORKSPACE}/fields overflow failure argv" \
        IPZ_TEST_SEQUENCE_LOG="${sequence_log}" "${root}/tests/e2e/run-remote.sh"; then
        fail 'runner ignored failed Fields overflow assertion'
    fi
    [[ "$(<"${sequence_log}")"$'\n' == $'1|test universal-admin-component-redesign.spec.js --project=chromium\n2|test universal-admin-component-redesign.spec.js --project=chromium\n3|test universal-admin-component-redesign.spec.js --project=chromium\nFINAL|test universal-admin-assertions.spec.js --project=chromium\nFINAL|test fields-table-overflow.spec.js --project=chromium\n' ]] || fail 'runner did not stop after failed Fields overflow assertion'
}

run_missing_transport_test() {
    if IPZ_RUN_REMOTE_TEST_MODE=1 IPZ_E2E_REMOTE_BIN="${WORKSPACE}/missing" "${RUNNER}" 2>"${WORKSPACE}/missing.err"; then
        fail 'runner accepted missing transport'
    fi
    grep -Fq 'E2E transport is missing or not executable:' "${WORKSPACE}/missing.err" || fail 'missing transport error differs'
}

[[ -x "${RUNNER}" ]] || fail "runner is missing or not executable: ${RUNNER}"
run_success_test
run_fail_fast_test
run_fields_overflow_fail_fast_test
run_missing_transport_test
printf 'run-remote contract tests passed\n'
