#!/usr/bin/env bash
set -Eeuo pipefail
umask 077

STEP_ID="STEP_050M07R13F2_SALVAGE_PUBLICATION_E2E_SELFTEST"
RESULT_PASS="PASS_STEP_050M07R13F2_SALVAGE_PUBLICATION_E2E_SELFTEST"

BASE="/opt/router-ops"
BIN="$BASE/bin"
TOKEN="e94a0859747d7b96f29c7fdafc2d0351ba603bb0a7e9e5a4"
ROOT="$BASE/public/r/$TOKEN"
LATEST="$ROOT/latest"
OLD="$ROOT/old"

TUNNEL_BASE="${TUNNEL_BASE:?TUNNEL_BASE is required}"
BASE_URL="$TUNNEL_BASE/r/$TOKEN"
LATEST_ROOT_URL="$BASE_URL/latest/"
OLD_ROOT_URL="$BASE_URL/old/"

FAILED_STATE="$BASE/state/publication-e2e-selftest/20260714-085432"
PREVIOUS_SOURCE_NAME="20260714-084455_vm130_router_ops_source_snapshot_r13e3"
NEW_SOURCE_NAME="20260714-085433_vm130_router_ops_source_snapshot_r13f"

TS="$(date -u +%Y%m%d-%H%M%S)"
STATE="$BASE/state/publication-e2e-selftest-salvage/$TS"
REPORT_BUILD="$STATE/report-build"
PROGRESS="$STATE/progress.log"

mkdir -p "$REPORT_BUILD"
chmod 700 "$STATE" "$REPORT_BUILD"
exec > >(tee -a "$PROGRESS") 2>&1

phase() {
    printf '>>> [%s] %s\n' "$1" "$2"
}

fail() {
    local reason="$1"
    printf '\nRESULT=STOP_%s\n' "$STEP_ID"
    printf 'FAILURE_REASON=%s\n' "$reason"
    printf 'STATE_DIR=%s\n' "$STATE"
    exit 1
}

trap 'rc=$?; fail "COMMAND_FAILED_RC_${rc}_LINE_${LINENO}"' ERR

single_latest_name() {
    local pattern="$1"
    local -a matches=()

    mapfile -t matches < <(
        find "$LATEST" \
            -mindepth 1 \
            -maxdepth 1 \
            -type d \
            -name "$pattern" \
            -printf '%f\n' |
        LC_ALL=C sort
    )

    [ "${#matches[@]}" -eq 1 ]
    printf '%s\n' "${matches[0]}"
}

phase PREFLIGHT "checking the completed source publication from R13F"

test -x "$BIN/router-publish-report"
test -x "$BIN/router-public-reindex"

test -d "$FAILED_STATE"
test -f "$FAILED_STATE/latest-before.txt"
test -f "$FAILED_STATE/source-publish-output.txt"

test -d "$LATEST/$NEW_SOURCE_NAME"
test -d "$OLD/$PREVIOUS_SOURCE_NAME"
test ! -e "$LATEST/$PREVIOUS_SOURCE_NAME"

VM130_SOURCE_URL="$(
    sed -n 's/^TRYCF_REPORT=//p' \
        "$FAILED_STATE/source-publish-output.txt" |
    tail -n 1
)"

PUBLISHED_DIR="$(
    sed -n 's/^PUBLISHED_DIR=//p' \
        "$FAILED_STATE/source-publish-output.txt" |
    tail -n 1
)"

PREVIOUS_MOVED_COUNT="$(
    sed -n 's/^PREVIOUS_MOVED_COUNT=//p' \
        "$FAILED_STATE/source-publish-output.txt" |
    tail -n 1
)"

test -n "$VM130_SOURCE_URL"
test "$PUBLISHED_DIR" = "$LATEST/$NEW_SOURCE_NAME"
test "$PREVIOUS_MOVED_COUNT" = "1"

phase ROTATION_VERIFY "checking latest to old rotation and unrelated objects"

grep -v '_vm130_router_ops_source_snapshot_' \
    "$FAILED_STATE/latest-before.txt" |
    LC_ALL=C sort \
    > "$STATE/unrelated-before.txt"

find "$LATEST" \
    -mindepth 1 \
    -maxdepth 1 \
    -type d \
    -printf '%f\n' |
    grep -v '_vm130_router_ops_source_snapshot_' |
    LC_ALL=C sort \
    > "$STATE/unrelated-after.txt"

cmp "$STATE/unrelated-before.txt" "$STATE/unrelated-after.txt"

find "$LATEST/$NEW_SOURCE_NAME" \
    -mindepth 1 \
    -maxdepth 1 \
    -printf '%f\n' |
    LC_ALL=C sort \
    > "$STATE/new-source-files.txt"

test -s "$STATE/new-source-files.txt"

phase HTTP_VERIFY "checking new source, old source and public indexes"

OLD_PREVIOUS_SOURCE_URL="$BASE_URL/old/$PREVIOUS_SOURCE_NAME/"

curl -fsS --max-time 30 "$VM130_SOURCE_URL" >/dev/null
curl -fsS --max-time 30 "$OLD_PREVIOUS_SOURCE_URL" >/dev/null
curl -fsS --max-time 30 "$LATEST_ROOT_URL" >/dev/null
curl -fsS --max-time 30 "$OLD_ROOT_URL" >/dev/null

phase LINKS "resolving current canonical latest objects"

LOCAL_M07_NAME="$(
    single_latest_name \
        '*_local_architecture_plan_vm101_autonomous_hmn_recovery*'
)"
GLOBAL_PLAN_NAME="$(
    single_latest_name '*_global_project_plan_wg_paid*'
)"
ACCESS_MAP_NAME="$(
    single_latest_name '*_xs_map_*'
)"
VM100_NAME="$(
    single_latest_name '*_vm100_git_source_*'
)"
VM101_NAME="$(
    single_latest_name '*_vm101_git_source_*'
)"
VM121_NAME="$(
    single_latest_name '*_vm121_git_source_*'
)"
VM101_MODEL_NAME="$(
    single_latest_name '*_vm101_model_*'
)"
VM101_METHODS_NAME="$(
    single_latest_name '*_vm101_methods_*'
)"

LOCAL_M07_PLAN_URL="$LATEST_ROOT_URL$LOCAL_M07_NAME/"
GLOBAL_PROJECT_PLAN_URL="$LATEST_ROOT_URL$GLOBAL_PLAN_NAME/"
ACCESS_MAP_URL="$LATEST_ROOT_URL$ACCESS_MAP_NAME/"
XS_MAP_URL="$ACCESS_MAP_URL"

VM100_PUBLIC_URL="$LATEST_ROOT_URL$VM100_NAME/"
VM101_PUBLIC_URL="$LATEST_ROOT_URL$VM101_NAME/"
VM121_PUBLIC_URL="$LATEST_ROOT_URL$VM121_NAME/"

VM101_MODEL_URL="$LATEST_ROOT_URL$VM101_MODEL_NAME/vm101-model.txt"
VM101_METHODS_URL="$LATEST_ROOT_URL$VM101_METHODS_NAME/"
ARCHITECTURE_PLAN_URL="$LOCAL_M07_PLAN_URL"

phase REPORT "building formal salvage and E2E verification report"

cp "$0" "$REPORT_BUILD/step-code.sh"
cp "$PROGRESS" "$REPORT_BUILD/progress.log"
cp \
    "$FAILED_STATE/source-publish-output.txt" \
    "$REPORT_BUILD/source-publish-output.txt"
cp \
    "$FAILED_STATE/latest-before.txt" \
    "$REPORT_BUILD/latest-before.txt"
cp "$STATE/unrelated-before.txt" "$REPORT_BUILD/unrelated-before.txt"
cp "$STATE/unrelated-after.txt" "$REPORT_BUILD/unrelated-after.txt"
cp "$STATE/new-source-files.txt" "$REPORT_BUILD/new-source-files.txt"

cat > "$REPORT_BUILD/report.txt" <<EOF_REPORT
RESULT=$RESULT_PASS
STEP=$STEP_ID
TIMESTAMP_UTC=$TS

CLASSIFICATION:
- Original R13F formal result: STOP.
- Core VM130 source publication: PASS.
- STOP cause: damaged parser line in the transferred STEP code.
- Publication workflow itself did not fail.

EXPECTED:
- A new VM130 source snapshot appears in latest/.
- The previous VM130 source snapshot moves to old/.
- Other latest objects remain unchanged.
- The STEP report is published by the same central publisher.

ACTUAL:
- new_source_folder=$NEW_SOURCE_NAME
- previous_source_folder=$PREVIOUS_SOURCE_NAME
- previous_moved_count=$PREVIOUS_MOVED_COUNT
- new_source_exists_in_latest=true
- previous_source_exists_in_old=true
- previous_source_absent_from_latest=true
- unrelated_latest_objects_unchanged=true
- new_source_http_verify=true
- old_source_http_verify=true
- latest_index_http_verify=true
- old_index_http_verify=true

CHANGES:
- VM100_CHANGED=false
- VM101_CHANGED=false
- VM121_CHANGED=false
- VM130_RUNTIME_CHANGED=false
- PUBLICATION_CODE_CHANGED=false

RUNTIME_IMPACT=false
ROLLBACK_AVAILABLE=true

VM130_SOURCE_URL=$VM130_SOURCE_URL
OLD_PREVIOUS_SOURCE_URL=$OLD_PREVIOUS_SOURCE_URL
EOF_REPORT

python3 - "$REPORT_BUILD/facts.json" <<PY
import json
import pathlib

facts = {
    "step_id": "$STEP_ID",
    "result": "$RESULT_PASS",
    "timestamp_utc": "$TS",
    "original_r13f_formal_result": "STOP",
    "original_r13f_core_publication_result": "PASS",
    "original_stop_reason": "transferred parser line corruption",
    "new_source_folder": "$NEW_SOURCE_NAME",
    "previous_source_folder": "$PREVIOUS_SOURCE_NAME",
    "previous_moved_count": int("$PREVIOUS_MOVED_COUNT"),
    "new_source_exists_in_latest": True,
    "previous_source_exists_in_old": True,
    "previous_source_absent_from_latest": True,
    "unrelated_latest_objects_unchanged": True,
    "new_source_http_verify": True,
    "old_source_http_verify": True,
    "latest_index_http_verify": True,
    "old_index_http_verify": True,
    "one_step_publication_workflow": True,
    "publication_code_changed": False,
    "router_machine_close_changed": False,
    "vm100_changed": False,
    "vm101_changed": False,
    "vm121_changed": False,
    "vm130_runtime_changed": False,
    "runtime_impact": False,
    "vm130_source_url": "$VM130_SOURCE_URL",
    "old_previous_source_url": "$OLD_PREVIOUS_SOURCE_URL"
}

pathlib.Path("$REPORT_BUILD/facts.json").write_text(
    json.dumps(facts, indent=2) + "\n"
)
PY

cat > "$REPORT_BUILD/verify.txt" <<EOF_VERIFY
RESULT=PASS
ORIGINAL_R13F_CORE_PUBLICATION=PASS
ORIGINAL_R13F_FORMAL_STOP_CAUSE=PARSER_LINE_CORRUPTION
ONE_STEP_PUBLICATION_WORKFLOW=true
LATEST_NEW_EXISTS=true
OLD_PREVIOUS_EXISTS=true
LATEST_PREVIOUS_ABSENT=true
PREVIOUS_MOVED_COUNT=1
UNRELATED_LATEST_OBJECTS_UNCHANGED=true
NEW_SOURCE_HTTP_VERIFY=true
OLD_SOURCE_HTTP_VERIFY=true
LATEST_INDEX_HTTP_VERIFY=true
OLD_INDEX_HTTP_VERIFY=true
PUBLICATION_CODE_CHANGED=false
ROUTER_MACHINE_CLOSE_CHANGED=false
VM100_CHANGED=false
VM101_CHANGED=false
VM121_CHANGED=false
VM130_RUNTIME_CHANGED=false
RUNTIME_IMPACT=false
EOF_VERIFY

cat > "$REPORT_BUILD/rollback.sh" <<EOF_ROLLBACK
#!/usr/bin/env bash
set -Eeuo pipefail

ROOT="$ROOT"
LATEST="\$ROOT/latest"
OLD="\$ROOT/old"

if [ -d "\$LATEST/$NEW_SOURCE_NAME" ]; then
    mv \
        "\$LATEST/$NEW_SOURCE_NAME" \
        "\$OLD/$NEW_SOURCE_NAME"
fi

if [ -d "\$OLD/$PREVIOUS_SOURCE_NAME" ] &&
   [ ! -e "\$LATEST/$PREVIOUS_SOURCE_NAME" ]; then
    mv \
        "\$OLD/$PREVIOUS_SOURCE_NAME" \
        "\$LATEST/$PREVIOUS_SOURCE_NAME"
fi

"$BIN/router-public-reindex" >/dev/null

echo "RESULT=PASS_ROLLBACK_$STEP_ID"
EOF_ROLLBACK

chmod 0755 "$REPORT_BUILD/rollback.sh"

phase PUBLISH_REPORT "publishing R13F2 report through central publisher"

REPORT_OUTPUT="$(
    TUNNEL_BASE="$TUNNEL_BASE" \
    "$BIN/router-publish-report" \
        step050m07r13f2_salvage_publication_e2e_selftest \
        "$REPORT_BUILD/step-code.sh" \
        "$REPORT_BUILD/report.txt" \
        "$REPORT_BUILD/facts.json" \
        "$REPORT_BUILD/progress.log" \
        "$REPORT_BUILD/verify.txt" \
        "$REPORT_BUILD/rollback.sh" \
        "$REPORT_BUILD/source-publish-output.txt" \
        "$REPORT_BUILD/latest-before.txt" \
        "$REPORT_BUILD/unrelated-before.txt" \
        "$REPORT_BUILD/unrelated-after.txt" \
        "$REPORT_BUILD/new-source-files.txt"
)"

printf '%s\n' "$REPORT_OUTPUT" |
    tee "$STATE/report-publish-output.txt"

STEP_REPORT_URL="$(
    printf '%s\n' "$REPORT_OUTPUT" |
    sed -n 's/^TRYCF_REPORT=//p' |
    tail -n 1
)"

REPORT_DIR="$(
    printf '%s\n' "$REPORT_OUTPUT" |
    sed -n 's/^PUBLISHED_DIR=//p' |
    tail -n 1
)"

test -n "$STEP_REPORT_URL"
test -d "$REPORT_DIR"

curl -fsS --max-time 30 "$STEP_REPORT_URL" >/dev/null
curl -fsS --max-time 30 "${STEP_REPORT_URL}report.txt" >/dev/null
curl -fsS --max-time 30 "${STEP_REPORT_URL}facts.json" >/dev/null
curl -fsS --max-time 30 "${STEP_REPORT_URL}verify.txt" >/dev/null
curl -fsS --max-time 30 "${STEP_REPORT_URL}step-code.sh" >/dev/null

printf '\nRESULT=%s\n' "$RESULT_PASS"
printf 'STEP_REPORT_URL=%s\n' "$STEP_REPORT_URL"
printf 'LATEST_ROOT_URL=%s\n' "$LATEST_ROOT_URL"
printf 'OLD_ROOT_URL=%s\n' "$OLD_ROOT_URL"
printf 'LOCAL_M07_PLAN_URL=%s\n' "$LOCAL_M07_PLAN_URL"
printf 'GLOBAL_PROJECT_PLAN_URL=%s\n' "$GLOBAL_PROJECT_PLAN_URL"
printf 'ACCESS_MAP_URL=%s\n' "$ACCESS_MAP_URL"
printf 'XS_MAP_URL=%s\n' "$XS_MAP_URL"
printf 'VM100_PUBLIC_URL=%s\n' "$VM100_PUBLIC_URL"
printf 'VM101_PUBLIC_URL=%s\n' "$VM101_PUBLIC_URL"
printf 'VM121_PUBLIC_URL=%s\n' "$VM121_PUBLIC_URL"
printf 'VM101_MODEL_URL=%s\n' "$VM101_MODEL_URL"
printf 'VM101_METHODS_URL=%s\n' "$VM101_METHODS_URL"
printf 'VM130_SOURCE_URL=%s\n' "$VM130_SOURCE_URL"
printf 'FACTS_URL=%sfacts.json\n' "$STEP_REPORT_URL"
printf 'VERIFY_URL=%sverify.txt\n' "$STEP_REPORT_URL"
printf 'ROLLBACK_URL=%srollback.sh\n' "$STEP_REPORT_URL"
printf 'ARCHITECTURE_PLAN_URL=%s\n' "$ARCHITECTURE_PLAN_URL"
