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

ROOT="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../../../.." && pwd -P)"
ARTIFACTS="$ROOT/modules/buildbox/e2e-runner/bin/e2e-k8s-artifacts"
DISPATCH="$ROOT/modules/workstation/claude/bin/e2e-k8s-dispatch"
MANIFEST="$ROOT/modules/workstation/claude/lib/e2e-k8s/job.yaml"
TEMP_DIR="$(mktemp -d)"
trap 'rm -rf -- "$TEMP_DIR"' EXIT
MARKER="$TEMP_DIR/remote.marker"
export MARKER

cat >"$TEMP_DIR/kubectl" <<'STUB'
#!/usr/bin/env bash
printf 'kubectl %s\n' "$*" >>"$MARKER"
exit 1
STUB
cat >"$TEMP_DIR/ssh" <<'STUB'
#!/usr/bin/env bash
printf 'ssh %s\n' "$*" >>"$MARKER"
exit 1
STUB
chmod +x "$TEMP_DIR/kubectl" "$TEMP_DIR/ssh"
export PATH="$TEMP_DIR:$PATH"
export IPZ_E2E_SSH_BIN="$TEMP_DIR/ssh"

expected_root='/workspace/plugins/international-press-zone/tests/e2e'
grep -Fq "readonly RESULTS_ROOT=\"$expected_root\"" "$ARTIFACTS"
if grep -Fq '/workspace/tests/e2e' "$ARTIFACTS"; then
    printf 'legacy artifact path remains in extractor\n' >&2
    exit 1
fi
# The public grammar remains exactly run-id plus a local destination; pod and
# remote source are derived internally and cannot be supplied by the caller.
grep -Fq 'Usage: e2e-k8s-artifacts [--stub] <run-id> <local-e2e-dir>' "$ARTIFACTS"
grep -Fq 'if (( $# != 2 )); then' "$ARTIFACTS"
! grep -Eq -- '--(pod|source)([=[:space:]]|$)' "$ARTIFACTS"

python3 - "$MANIFEST" <<'PY'
import re
import sys
from pathlib import Path
import yaml

class UniqueLoader(yaml.SafeLoader):
    pass

def construct_mapping(loader, node, deep=False):
    mapping = {}
    for key_node, value_node in node.value:
        key = loader.construct_object(key_node, deep=deep)
        if key in mapping:
            raise AssertionError(f"duplicate YAML key in one mapping: {key}")
        mapping[key] = loader.construct_object(value_node, deep=deep)
    return mapping

UniqueLoader.add_constructor(
    yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, construct_mapping
)
raw = Path(sys.argv[1]).read_text(encoding="utf-8")
assert "__ARTIFACT_EXPORTER_WAIT_SECONDS__" in raw
# Render template tokens to scalar dummy values before structural YAML parsing.
text = re.sub(r"__[A-Z0-9_]+__", "dummy", raw)
doc = yaml.load(text, Loader=UniqueLoader)
pod_spec = doc["spec"]["template"]["spec"]
containers = {item["name"]: item for item in pod_spec["containers"]}
init_names = {item["name"] for item in pod_spec["initContainers"]}
assert "artifact-exporter" in containers
assert "artifact-exporter" not in init_names
exporter = containers["artifact-exporter"]
assert exporter.get("restartPolicy") != "Always"
playwright = containers["playwright"]
playwright_mounts = {(m["name"], m["mountPath"]) for m in playwright["volumeMounts"]}
exporter_mounts = {(m["name"], m["mountPath"]) for m in exporter["volumeMounts"]}
assert ("run-workspace", "/workspace") in playwright_mounts
assert ("run-workspace", "/workspace") in exporter_mounts
assert playwright_mounts & exporter_mounts
assert "activeDeadlineSeconds" in doc["spec"]
assert "ttlSecondsAfterFinished" in doc["spec"]
script = exporter["args"][0]
assert "wait_seconds=dummy" in script
assert 'test "${elapsed}" -lt "${wait_seconds}"' in script
assert "elapsed=$((elapsed + 1))" in script
assert "while ! test -f /workspace/.ipz-e2e-client-finished; do" not in script
PY

# Execute the actual manifest script with a local workspace stand-in. This proves
# the absent-marker path terminates successfully rather than merely looking
# bounded in a grep assertion.
python3 - "$MANIFEST" "$TEMP_DIR/exporter.sh" "$TEMP_DIR/workspace" <<'PY'
import sys
from pathlib import Path
import yaml

manifest, output, workspace = sys.argv[1:]
doc = yaml.safe_load(Path(manifest).read_text(encoding="utf-8"))
exporter = next(c for c in doc["spec"]["template"]["spec"]["containers"] if c["name"] == "artifact-exporter")
script = exporter["args"][0]
script = script.replace("/workspace", workspace)
script = script.replace("__ARTIFACT_EXPORTER_WAIT_SECONDS__", "2")
script = script.replace("__ARTIFACT_EXPORTER_SECONDS__", "0")
Path(output).write_text(script, encoding="utf-8")
PY
mkdir -p "$TEMP_DIR/workspace"
start_seconds=$SECONDS
set +e
timeout 5 sh "$TEMP_DIR/exporter.sh" 2>"$TEMP_DIR/exporter-absent.err"
status=$?
set -e
[[ $status -eq 0 ]]
(( SECONDS - start_seconds < 5 ))
grep -Fxq 'artifact-exporter: the client-finished marker never appeared within 2s; exiting so the pod can be reclaimed' "$TEMP_DIR/exporter-absent.err"

: >"$TEMP_DIR/workspace/.ipz-e2e-client-finished"
set +e
timeout 3 sh "$TEMP_DIR/exporter.sh" 2>"$TEMP_DIR/exporter-present.err"
status=$?
set -e
[[ $status -eq 0 ]]
! grep -Fq 'client-finished marker never appeared' "$TEMP_DIR/exporter-present.err"

run_bad_ttl() {
    local value="$1"
    : >"$MARKER"
    set +e
    timeout 9 "$DISPATCH" --debug-ttl "$value" run-id mirror debian1 -- /bin/true >"$TEMP_DIR/out" 2>"$TEMP_DIR/err"
    local status=$?
    set -e
    [[ $status -eq 6 ]]
    [[ ! -s "$MARKER" ]]
    grep -Fq "debug TTL value $value is invalid; accepted range is 5 to 30 minutes." "$TEMP_DIR/err"
}
run_bad_ttl 4
run_bad_ttl 31
run_bad_ttl abc

: >"$MARKER"
set +e
timeout 9 "$DISPATCH" --debug-ttl >"$TEMP_DIR/out" 2>"$TEMP_DIR/err"
status=$?
set -e
[[ $status -eq 6 ]]
[[ ! -s "$MARKER" ]]
grep -Fq 'debug TTL value <missing> is invalid; accepted range is 5 to 30 minutes.' "$TEMP_DIR/err"

# A valid value passes parsing and reaches the remote-node gate. The ssh stub
# proves it was not rejected locally as admission 6 by the option parser.
: >"$MARKER"
set +e
timeout 9 env IPZ_E2E_RUNNER_IMAGE=runner IPZ_E2E_SNAPSHOT_DIR=/snapshot \
    "$DISPATCH" --debug-ttl 10 run-id mirror debian1 -- /bin/true \
    >"$TEMP_DIR/out" 2>"$TEMP_DIR/err"
status=$?
set -e
[[ -s "$MARKER" ]]
! grep -Fq 'debug TTL value 10 is invalid' "$TEMP_DIR/err"

! grep -Fq 'no-cleanup' "$DISPATCH"
! grep -Fq 'no-cleanup' "$MANIFEST"

cat >"$TEMP_DIR/render-ssh" <<'STUB'
#!/usr/bin/env bash
for ((index = 1; index <= $#; index++)); do
    argument="${!index}"
    case "$argument" in
        apply)
            payload_index=$((index + 1))
            printf '%s' "${!payload_index}" | base64 --decode >"$CAPTURE_MANIFEST"
            exit 0
            ;;
        wait)
            printf 'K8S_RESULT\tclient\t0\n'
            exit 0
            ;;
        ensure-namespace|node-ready|mirror|image|stream-logs)
            exit 0
            ;;
    esac
done
exit 0
STUB
chmod +x "$TEMP_DIR/render-ssh"

render_debug_manifest() {
    local ttl="$1"
    local output="$2"
    CAPTURE_MANIFEST="$output" \
        IPZ_E2E_SSH_BIN="$TEMP_DIR/render-ssh" \
        IPZ_E2E_RUNNER_IMAGE=runner \
        IPZ_E2E_SNAPSHOT_DIR=/snapshot \
        IPZ_E2E_K8S_WAIT_SECONDS=17 \
        "$DISPATCH" --debug-ttl "$ttl" "render-$ttl" mirror debian1 -- /bin/true \
        >"$TEMP_DIR/render-$ttl.out" 2>"$TEMP_DIR/render-$ttl.err"
}
render_debug_manifest 5 "$TEMP_DIR/render-5.yaml"
render_debug_manifest 30 "$TEMP_DIR/render-30.yaml"
CAPTURE_MANIFEST="$TEMP_DIR/render-default.yaml" \
    IPZ_E2E_SSH_BIN="$TEMP_DIR/render-ssh" \
    IPZ_E2E_RUNNER_IMAGE=runner \
    IPZ_E2E_SNAPSHOT_DIR=/snapshot \
    IPZ_E2E_K8S_WAIT_SECONDS=17 \
    "$DISPATCH" render-default mirror debian1 -- /bin/true \
    >"$TEMP_DIR/render-default.out" 2>"$TEMP_DIR/render-default.err"
wait_5="$(grep -E '^[[:space:]]*wait_seconds=[0-9]+$' "$TEMP_DIR/render-5.yaml" | tr -d '[:space:]' | cut -d= -f2)"
wait_30="$(grep -E '^[[:space:]]*wait_seconds=[0-9]+$' "$TEMP_DIR/render-30.yaml" | tr -d '[:space:]' | cut -d= -f2)"
[[ "$wait_5" == 137 ]]
[[ "$wait_30" == "$wait_5" ]]
! grep -Fq '__ARTIFACT_EXPORTER_WAIT_SECONDS__' "$TEMP_DIR/render-5.yaml"
! grep -Eq '__[A-Z0-9_]+__' "$TEMP_DIR/render-5.yaml"

# In every production rendering, including the default non-debug lane, the Job
# deadline must leave the exporter time to reach its own deadline and exit.
python3 - "$TEMP_DIR/render-default.yaml" "$TEMP_DIR/render-5.yaml" "$TEMP_DIR/render-30.yaml" <<'PY'
import re
import sys
from pathlib import Path
import yaml

for path in sys.argv[1:]:
    doc = yaml.safe_load(Path(path).read_text(encoding="utf-8"))
    deadline = doc["spec"]["activeDeadlineSeconds"]
    exporter = next(
        container
        for container in doc["spec"]["template"]["spec"]["containers"]
        if container["name"] == "artifact-exporter"
    )
    script = exporter["args"][0]
    wait_match = re.search(r"^\s*wait_seconds=(\d+)\s*$", script, re.MULTILINE)
    retention_matches = re.findall(r"^\s*sleep (\d+)\s*$", script, re.MULTILINE)
    assert wait_match and retention_matches, (path, script)
    wait_seconds = int(wait_match.group(1))
    retention_seconds = int(retention_matches[-1])
    assert deadline > wait_seconds + retention_seconds, (
        path,
        deadline,
        wait_seconds,
        retention_seconds,
    )
PY

bash -n "$DISPATCH"
bash -n "$ARTIFACTS"

printf 'e2e-k8s-artifacts tests passed\n'
