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

[ "$(id -un)" = "ops" ] || {
  echo "STOP: запускать на router-ops пользователем ops"
  exit 1
}

STEP="STEP_050M07R05A_CAPTURE_GENERATOR_TRACEBACK"

TOKEN="e94a0859747d7b96f29c7fdafc2d0351ba603bb0a7e9e5a4"
PUBLIC_BASE="https://helena-background-beam-harry.trycloudflare.com/r/${TOKEN}"

ROOT="/opt/router-ops"
PUBROOT="${ROOT}/public/r/${TOKEN}"

FAILED_SLUG="20260712-092211_step050m07r05_generate_complete_canonical_candidates"
FAILED_REPORT="${PUBROOT}/${FAILED_SLUG}"
FAILED_STEP="${FAILED_REPORT}/step.sh"
FAILED_FACTS="${FAILED_REPORT}/facts.json"

BUILD_TS="$(date -u +%Y%m%d-%H%M%S)"
REPORT_SLUG="${BUILD_TS}_step050m07r05a_capture_generator_traceback"
REPORT_DIR="${PUBROOT}/${REPORT_SLUG}"

TRYCF_REPORT="${PUBLIC_BASE}/${REPORT_SLUG}/"
REPORT_TXT="${TRYCF_REPORT}report.txt"
FACTS_JSON="${TRYCF_REPORT}facts.json"

ARCHITECTURE_PLAN="${PUBLIC_BASE}/20260711-181158_local_architecture_plan_vm101_autonomous_hmn_recovery/"
XS_MAP="${PUBLIC_BASE}/20260711-120734_xs_map_audit_repair_publish/"
GLOBAL_PROJECT_PLAN="${PUBLIC_BASE}/20260711-123348_global_project_plan_wg_paid/"
VM101_REFERENCE="${PUBLIC_BASE}/vm101-reference/current/"
VM101_CANONICAL="${PUBLIC_BASE}/vm101-canonical/current/"

GENERATOR="/tmp/step050m07r05a_extracted_generator.py"

WORKSPACE="UNRESOLVED"
CANONICAL_ID="UNRESOLVED"
SOURCE_CANONICAL_ID="UNRESOLVED"
REFERENCE_ID="UNRESOLVED"
SOURCE_REFERENCE_ID="UNRESOLVED"

GENERATOR_RC="NOT_RUN"
GENERATOR_EXTRACTED=false
GENERATOR_LOG_CREATED=false
GENERATED_COUNT=0
CHANGED_COUNT=0

mkdir -p "$REPORT_DIR"

cp -a "$0" "$REPORT_DIR/step.sh"
chmod 600 "$REPORT_DIR/step.sh"

[ -s "$FAILED_STEP" ] || {
  echo "STOP: отсутствует $FAILED_STEP"
  exit 2
}

[ -s "$FAILED_FACTS" ] || {
  echo "STOP: отсутствует $FAILED_FACTS"
  exit 3
}

eval "$(
  python3 - "$FAILED_FACTS" <<'PY'
import json
import shlex
import sys

data = json.load(open(sys.argv[1], encoding="utf-8"))
canonical = data["canonical"]

values = {
    "WORKSPACE": canonical["workspace"],
    "CANONICAL_ID": canonical["canonical_id"],
    "SOURCE_CANONICAL_ID": canonical["source_canonical_id"],
    "REFERENCE_ID": canonical["reference_id"],
    "SOURCE_REFERENCE_ID": canonical["source_reference_id"],
}

for key, value in values.items():
    print(f"{key}={shlex.quote(str(value))}")
PY
)"

for required in \
  "$WORKSPACE" \
  "$WORKSPACE/source" \
  "$WORKSPACE/candidate" \
  "$WORKSPACE/contracts/source-locks.tsv" \
  "$WORKSPACE/contracts/edit-map-private.json" \
  "$WORKSPACE/contracts/replacement-blueprints.json"
do
  [ -e "$required" ] || {
    echo "STOP: отсутствует failed-workspace component: $required"
    exit 4
  }
done

python3 - \
  "$FAILED_STEP" \
  "$GENERATOR" \
  "$REPORT_DIR/extraction.json" <<'PY'
import hashlib
import json
import sys
from pathlib import Path

source_path = Path(sys.argv[1])
generator_path = Path(sys.argv[2])
report_path = Path(sys.argv[3])

text = source_path.read_text(
    encoding="utf-8",
    errors="strict",
)

marker = '"$REPORT_DIR/generator-log.json" <<\'PY\'\n'

count = text.count(marker)

if count != 1:
    raise SystemExit(
        f"generator marker count={count}, expected=1"
    )

start = text.index(marker) + len(marker)
end_marker = "\nPY\n"
end = text.index(end_marker, start)

payload = text[start:end]

if "transform_refresh_pool_safe" not in payload:
    raise SystemExit(
        "extracted payload lacks generator functions"
    )

if "generator_result" not in payload:
    raise SystemExit(
        "extracted payload lacks generator result"
    )

generator_path.write_text(
    payload + "\n",
    encoding="utf-8",
)

result = {
    "schema": "r05-generator-extraction-v1",
    "source_step": str(source_path),
    "generator_path": str(generator_path),
    "bytes": generator_path.stat().st_size,
    "lines": len(payload.splitlines()),
    "sha256": hashlib.sha256(
        generator_path.read_bytes()
    ).hexdigest(),
    "passed": True,
}

report_path.write_text(
    json.dumps(
        result,
        ensure_ascii=False,
        indent=2,
    ) + "\n",
    encoding="utf-8",
)
PY

GENERATOR_EXTRACTED=true
chmod 600 "$GENERATOR"

python3 -m py_compile "$GENERATOR"

rm -f \
  "$REPORT_DIR/generator-rerun.json" \
  "$REPORT_DIR/generator.stdout" \
  "$REPORT_DIR/generator.stderr"

set +e

python3 \
  "$GENERATOR" \
  "$WORKSPACE" \
  "$CANONICAL_ID" \
  "$SOURCE_CANONICAL_ID" \
  "$REFERENCE_ID" \
  "$SOURCE_REFERENCE_ID" \
  "$REPORT_DIR/generator-rerun.json" \
  > "$REPORT_DIR/generator.stdout" \
  2> "$REPORT_DIR/generator.stderr"

GENERATOR_RC=$?

set -e

if [ -s "$REPORT_DIR/generator-rerun.json" ]; then
  GENERATOR_LOG_CREATED=true

  GENERATED_COUNT="$(
    python3 - "$REPORT_DIR/generator-rerun.json" <<'PY'
import json
import sys

data = json.load(open(sys.argv[1], encoding="utf-8"))
print(data.get("generated_count", 0))
PY
  )"

  CHANGED_COUNT="$(
    python3 - "$REPORT_DIR/generator-rerun.json" <<'PY'
import json
import sys

data = json.load(open(sys.argv[1], encoding="utf-8"))
print(data.get("changed_count", 0))
PY
  )"
fi

if [ "$GENERATOR_RC" -eq 0 ]; then
  DECISION="PASS_${STEP}"
  STEP_EXECUTION="PASS"
  OPERATION_RESULT="GENERATOR_RERUN_COMPLETED"
  FAILURE_CLASS="NONE"
else
  DECISION="STOP_${STEP}_GENERATOR_EXCEPTION_REPRODUCED"
  STEP_EXECUTION="STOP"
  OPERATION_RESULT="GENERATOR_TRACEBACK_CAPTURED"
  FAILURE_CLASS="$(
    python3 - "$REPORT_DIR/generator.stderr" <<'PY'
import re
import sys
from pathlib import Path

text = Path(sys.argv[1]).read_text(
    encoding="utf-8",
    errors="replace",
)

lines = [
    line.strip()
    for line in text.splitlines()
    if line.strip()
]

result = "UNKNOWN_EXCEPTION"

for line in reversed(lines):
    match = re.match(
        r"([A-Za-z_][A-Za-z0-9_.]*(?:Error|Exception)):",
        line,
    )

    if match:
        result = match.group(1)
        break

print(result)
PY
  )"
fi

python3 - \
  "$REPORT_DIR/generator.stderr" \
  "$REPORT_DIR/traceback-summary.json" \
  "$GENERATOR_RC" \
  "$FAILURE_CLASS" <<'PY'
import json
import sys
from pathlib import Path

stderr_path = Path(sys.argv[1])
output_path = Path(sys.argv[2])
rc = int(sys.argv[3])
failure_class = sys.argv[4]

text = stderr_path.read_text(
    encoding="utf-8",
    errors="replace",
)

lines = text.splitlines()

result = {
    "schema": "r05-generator-traceback-v1",
    "generator_rc": rc,
    "failure_class": failure_class,
    "stderr_line_count": len(lines),
    "stderr_tail": lines[-40:],
    "traceback_captured": rc != 0 and bool(lines),
}

output_path.write_text(
    json.dumps(
        result,
        ensure_ascii=False,
        indent=2,
    ) + "\n",
    encoding="utf-8",
)
PY

cat > "$REPORT_DIR/report.txt" <<EOF
=== ${STEP} RESULT ===
step=${STEP}
decision=${DECISION}
step_execution=${STEP_EXECUTION}
operation_result=${OPERATION_RESULT}
production_health=UNCHANGED
milestone_status=M07_IN_PROGRESS

source:
  failed_step=${FAILED_STEP}
  failed_facts=${FAILED_FACTS}
  workspace=${WORKSPACE}
  canonical_id=${CANONICAL_ID}
  source_canonical_id=${SOURCE_CANONICAL_ID}
  reference_id=${REFERENCE_ID}
  source_reference_id=${SOURCE_REFERENCE_ID}

diagnostic:
  generator_extracted=${GENERATOR_EXTRACTED}
  generator_rc=${GENERATOR_RC}
  generator_log_created=${GENERATOR_LOG_CREATED}
  generated_count=${GENERATED_COUNT}
  changed_count=${CHANGED_COUNT}
  failure_class=${FAILURE_CLASS}
  traceback_file=generator.stderr

safety:
  local_only=true
  vm101_contacted=false
  vm101_modified=false
  canonical_current_updated=false
  canonical_state_updated=false
  installation_allowed=false
  network_changed=false
  services_changed=false
  runtime_state_changed=false
  refresh_ran=false
  rebalance_ran=false

next_step:
  PATCH_EXACT_GENERATOR_FAILURE_AND_RESUME_R05

TRYCF_REPORT=${TRYCF_REPORT}
REPORT_TXT=${REPORT_TXT}
FACTS_JSON=${FACTS_JSON}
ARCHITECTURE_PLAN=${ARCHITECTURE_PLAN}
XS_MAP=${XS_MAP}
GLOBAL_PROJECT_PLAN=${GLOBAL_PROJECT_PLAN}
VM101_REFERENCE=${VM101_REFERENCE}
VM101_CANONICAL=${VM101_CANONICAL}
EOF

python3 - \
  "$STEP" \
  "$DECISION" \
  "$STEP_EXECUTION" \
  "$OPERATION_RESULT" \
  "$WORKSPACE" \
  "$CANONICAL_ID" \
  "$SOURCE_CANONICAL_ID" \
  "$REFERENCE_ID" \
  "$SOURCE_REFERENCE_ID" \
  "$GENERATOR_EXTRACTED" \
  "$GENERATOR_RC" \
  "$GENERATOR_LOG_CREATED" \
  "$GENERATED_COUNT" \
  "$CHANGED_COUNT" \
  "$FAILURE_CLASS" \
  "$TRYCF_REPORT" \
  "$REPORT_TXT" \
  "$FACTS_JSON" \
  "$ARCHITECTURE_PLAN" \
  "$XS_MAP" \
  "$GLOBAL_PROJECT_PLAN" \
  "$VM101_REFERENCE" \
  "$VM101_CANONICAL" \
  > "$REPORT_DIR/facts.json" <<'PY'
import json
import sys

(
    step,
    decision,
    step_execution,
    operation_result,
    workspace,
    canonical_id,
    source_canonical_id,
    reference_id,
    source_reference_id,
    generator_extracted,
    generator_rc,
    generator_log_created,
    generated_count,
    changed_count,
    failure_class,
    report,
    report_txt,
    facts_json,
    architecture,
    xs_map,
    global_plan,
    reference_url,
    canonical_url,
) = sys.argv[1:]

print(json.dumps({
    "schema": "router-step-facts-v1",
    "step": step,
    "assessment": {
        "decision": decision,
        "step_execution": step_execution,
        "operation_result": operation_result,
        "production_health": "UNCHANGED",
        "milestone_status": "M07_IN_PROGRESS",
        "all_ok": step_execution == "PASS",
    },
    "canonical": {
        "workspace": workspace,
        "canonical_id": canonical_id,
        "source_canonical_id": source_canonical_id,
        "reference_id": reference_id,
        "source_reference_id": source_reference_id,
    },
    "diagnostic": {
        "generator_extracted":
            generator_extracted == "true",
        "generator_rc": int(generator_rc),
        "generator_log_created":
            generator_log_created == "true",
        "generated_count": int(generated_count),
        "changed_count": int(changed_count),
        "failure_class": failure_class,
        "traceback_file": "generator.stderr",
        "traceback_summary_file":
            "traceback-summary.json",
    },
    "safety": {
        "local_only": True,
        "vm101_contacted": False,
        "vm101_modified": False,
        "canonical_current_updated": False,
        "canonical_state_updated": False,
        "installation_allowed": False,
        "network_changed": False,
        "services_changed": False,
        "runtime_state_changed": False,
        "refresh_ran": False,
        "rebalance_ran": False,
    },
    "next_step":
        "PATCH_EXACT_GENERATOR_FAILURE_AND_RESUME_R05",
    "publish": {
        "trycf_report": report,
        "report_txt": report_txt,
        "facts_json": facts_json,
        "architecture_plan": architecture,
        "xs_map": xs_map,
        "global_project_plan": global_plan,
        "vm101_reference": reference_url,
        "vm101_canonical": canonical_url,
    },
}, ensure_ascii=False, indent=2))
PY

cat > "$REPORT_DIR/index.html" <<EOF
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<title>${STEP}</title>
</head>
<body style="font-family:system-ui;max-width:1100px;margin:40px auto;padding:0 20px">
<h1>${STEP}</h1>
<ul>
<li><a href="report.txt">report.txt</a></li>
<li><a href="facts.json">facts.json</a></li>
<li><a href="extraction.json">extraction.json</a></li>
<li><a href="traceback-summary.json">traceback-summary.json</a></li>
<li><a href="generator.stderr">generator.stderr</a></li>
<li><a href="generator.stdout">generator.stdout</a></li>
<li><a href="generator-rerun.json">generator-rerun.json</a></li>
<li><a href="step.sh">step.sh</a></li>
</ul>
</body>
</html>
EOF

find "$REPORT_DIR" \
  -type f \
  ! -name SHA256SUMS \
  -print0 |
  sort -z |
  xargs -0 sha256sum \
  > "$REPORT_DIR/SHA256SUMS"

echo
echo "decision=$DECISION"
echo "step_execution=$STEP_EXECUTION"
echo "operation_result=$OPERATION_RESULT"
echo "generator_rc=$GENERATOR_RC"
echo "failure_class=$FAILURE_CLASS"
echo "generated_count=$GENERATED_COUNT"
echo "changed_count=$CHANGED_COUNT"
echo "vm101_contacted=false"
echo "vm101_modified=false"

echo
echo "TRACEBACK_TAIL_BEGIN"
tail -n 30 "$REPORT_DIR/generator.stderr" || true
echo "TRACEBACK_TAIL_END"

echo
echo "TRYCF_REPORT=$TRYCF_REPORT"
echo "REPORT_TXT=$REPORT_TXT"
echo "FACTS_JSON=$FACTS_JSON"
echo "ARCHITECTURE_PLAN=$ARCHITECTURE_PLAN"
echo "XS_MAP=$XS_MAP"
echo "GLOBAL_PROJECT_PLAN=$GLOBAL_PROJECT_PLAN"
echo "VM101_REFERENCE=$VM101_REFERENCE"
echo "VM101_CANONICAL=$VM101_CANONICAL"
