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

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
ADMIN="${ROOT}/admin"

run_php_syntax() {
    find "${ROOT}/includes" "${ROOT}/tests" -name '*.php' -print0 \
        | xargs -0 -n1 php -l
}

run_test() {
    composer --working-dir="${ROOT}" test
    # Standalone regressions declare their own WordPress stubs, so they cannot
    # share a PHPUnit process with the enumerated suite. The three true live-
    # WordPress integration tests run separately against the sanctioned E2E
    # stack; they are never accepted as standalone skips or known-failing debt.
    "${ROOT}/tests/run-unit-tests.sh"         "${ROOT}/tests/unit"         "${ROOT}/tests/Unit/SiteContent/BlockSegmentCodecTest.php"         "${ROOT}/tests/integration/WorkflowIntegrationTest.php"         "${ROOT}/tests/integration/Core/CacheWarmerRegressionStandaloneTest.php"
    "${ROOT}/tests/run-wordpress-integration-tests.sh"
}

run_phpcs() {
    local git_root prefix base merge_base
    git_root="$(git -C "${ROOT}" rev-parse --show-toplevel)"
    prefix="$(git -C "${ROOT}" rev-parse --show-prefix)"
    base="${UI_GATE_BASE:-origin/master}"
    merge_base="$(git -C "${ROOT}" merge-base "${base}" HEAD)" || {
        printf 'PHP baseline gate requires a resolvable comparison base: %s\n' "${base}" >&2
        return 2
    }

    mapfile -t files < <(
        {
            git -C "${ROOT}" diff --name-only "${merge_base}...HEAD"
            git -C "${ROOT}" diff --cached --name-only
            git -C "${ROOT}" diff --name-only
            git -C "${ROOT}" ls-files --others --exclude-standard
        } | sort -u | while IFS= read -r file; do
            file="${file#${prefix}}"
            case "${file}" in includes/*.php) printf '%s\n' "${file}" ;; esac
        done
    )

    if ((${#files[@]} == 0)); then
        printf 'phpcs-baseline: no changed PHP files\n'
        return 0
    fi

    (
        cd "${ROOT}"
        php tools/phpcs-baseline.php check "${files[@]}"
    )
}

run_phpstan() {
    composer --working-dir="${ROOT}" phpstan
}

run_admin_lint() {
    npm --prefix "${ADMIN}" run lint:js
}

run_build() {
    npm --prefix "${ADMIN}" run build
}

run_ui_architecture() {
    /usr/bin/node --test "${ROOT}/tools/ui-inventory.test.mjs" "${ROOT}/tools/ui-gate.test.mjs"
    /usr/bin/node "${ROOT}/tools/ui-inventory.mjs" --check
    /usr/bin/node "${ROOT}/tools/ui-gate.mjs"
}

case "${1:-all}" in
    php-syntax) run_php_syntax ;;
    test) run_test ;;
    phpcs) run_phpcs ;;
    phpstan) run_phpstan ;;
    admin-lint) run_admin_lint ;;
    build) run_build ;;
    ui-architecture) run_ui_architecture ;;
    all)
        run_php_syntax
        run_test
        run_phpcs
        run_phpstan
        run_admin_lint
        run_build
        run_ui_architecture
        ;;
    *)
        printf 'Usage: %s {all|php-syntax|test|phpcs|phpstan|admin-lint|build|ui-architecture}\n' "$0" >&2
        exit 64
        ;;
esac
