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

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

usage() {
  cat <<'USAGE'
Usage:
  run_multi_rir_ccr_replay_verify.sh --rir <rir[,rir...]> [--mode snapshot|delta|both] [--keep-db]

Options:
  --rir <list>       Comma-separated RIR list, e.g. apnic or apnic,ripe
  --mode <mode>      snapshot | delta | both (default: both)
  --keep-db          Keep per-run RocksDB directories (default: remove after verify)
  --bundle-root <p>  Override bundle root
  --out-root <p>     Override output root (default: rpki/target/replay)
  --run-tag <tag>    Override timestamp suffix for all RIR runs
USAGE
}

MODE="both"
KEEP_DB=0
RIR_LIST=""
BUNDLE_ROOT="${BUNDLE_ROOT:-/home/yuyr/dev/rust_playground/routinator/bench/multi_rir_demo/runs/20260316-112341-multi-final3}"
OUT_ROOT="${OUT_ROOT:-$ROOT_DIR/target/replay}"
RUN_TAG="${RUN_TAG:-$(date -u +%Y%m%dT%H%M%SZ)}"

while [[ $# -gt 0 ]]; do
  case "$1" in
    --rir)
      shift
      RIR_LIST="${1:-}"
      ;;
    --mode)
      shift
      MODE="${1:-}"
      ;;
    --keep-db)
      KEEP_DB=1
      ;;
    --bundle-root)
      shift
      BUNDLE_ROOT="${1:-}"
      ;;
    --out-root)
      shift
      OUT_ROOT="${1:-}"
      ;;
    --run-tag)
      shift
      RUN_TAG="${1:-}"
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      echo "unknown argument: $1" >&2
      usage >&2
      exit 2
      ;;
  esac
  shift || true
done

if [[ -z "$RIR_LIST" ]]; then
  echo "--rir is required" >&2
  usage >&2
  exit 2
fi
case "$MODE" in
  snapshot|delta|both) ;;
  *)
    echo "invalid --mode: $MODE" >&2
    usage >&2
    exit 2
    ;;
esac

CASE_INFO_SCRIPT="$ROOT_DIR/scripts/payload_replay/multi_rir_case_info.py"
mkdir -p "$OUT_ROOT"
RUN_ROOT="$OUT_ROOT/$RUN_TAG"
mkdir -p "$RUN_ROOT"

cargo build --release --bin rpki --bin ccr_to_routinator_csv --bin ccr_verify >/dev/null

summary_md="$RUN_ROOT/multi_rir_ccr_replay_verify_${RUN_TAG}_summary.md"
summary_json="$RUN_ROOT/multi_rir_ccr_replay_verify_${RUN_TAG}_summary.json"

python3 - <<'PY' >/dev/null
PY

summary_json_tmp="$(mktemp)"
printf '[]' > "$summary_json_tmp"

run_one_mode() {
  local rir="$1"
  local mode="$2"
  local run_dir="$3"
  local trust_anchor="$4"
  local tal_path="$5"
  local ta_path="$6"
  local base_archive="$7"
  local base_locks="$8"
  local base_csv="$9"
  local delta_archive="${10}"
  local delta_locks="${11}"
  local delta_csv="${12}"
  local snapshot_validation_time="${13}"
  local delta_validation_time="${14}"

  local db_dir="$run_dir/${rir}_${mode}_db"
  local report_json="$run_dir/${rir}_${mode}_report.json"
  local run_log="$run_dir/${rir}_${mode}_run.log"
  local ccr_path="$run_dir/${rir}_${mode}.ccr"
  local csv_path="$run_dir/${rir}_${mode}_ccr_vrps.csv"
  local compare_md="$run_dir/${rir}_${mode}_ccr_compare_summary.md"
  local only_ours="$run_dir/${rir}_${mode}_ccr_only_in_ours.csv"
  local only_record="$run_dir/${rir}_${mode}_ccr_only_in_record.csv"
  local verify_json="$run_dir/${rir}_${mode}_ccr_verify.json"
  local meta_json="$run_dir/${rir}_${mode}_meta.json"

  rm -rf "$db_dir"

  local -a cmd=(target/release/rpki --db "$db_dir" --tal-path "$tal_path" --ta-path "$ta_path")
  if [[ "$mode" == "snapshot" ]]; then
    cmd+=(--payload-replay-archive "$base_archive" --payload-replay-locks "$base_locks" --validation-time "$snapshot_validation_time")
  else
    cmd+=(
      --payload-base-archive "$base_archive"
      --payload-base-locks "$base_locks"
      --payload-base-validation-time "$snapshot_validation_time"
      --payload-delta-archive "$delta_archive"
      --payload-delta-locks "$delta_locks"
      --validation-time "$delta_validation_time"
    )
  fi
  cmd+=(--report-json "$report_json" --ccr-out "$ccr_path")

  local start_s end_s duration_s
  start_s="$(date +%s)"
  (
    echo "# ${rir} ${mode} command:"
    printf '%q ' "${cmd[@]}"
    echo
    echo
    "${cmd[@]}"
  ) 2>&1 | tee "$run_log" >/dev/null
  end_s="$(date +%s)"
  duration_s="$((end_s - start_s))"

  target/release/ccr_to_routinator_csv \
    --ccr "$ccr_path" \
    --out "$csv_path" \
    --trust-anchor "$trust_anchor" >/dev/null

  local record_csv
  if [[ "$mode" == "snapshot" ]]; then
    record_csv="$base_csv"
  else
    record_csv="$delta_csv"
  fi
  ./scripts/payload_replay/compare_with_routinator_record.sh \
    "$csv_path" \
    "$record_csv" \
    "$compare_md" \
    "$only_ours" \
    "$only_record" >/dev/null

  target/release/ccr_verify \
    --ccr "$ccr_path" \
    --db "$db_dir" > "$verify_json"

  python3 - "$report_json" "$meta_json" "$mode" "$duration_s" <<'PY'
import json, sys
from pathlib import Path
report = json.loads(Path(sys.argv[1]).read_text(encoding='utf-8'))
meta = {
  'mode': sys.argv[3],
  'duration_seconds': int(sys.argv[4]),
  'validation_time': report.get('validation_time_rfc3339_utc'),
  'publication_points_processed': report['tree']['instances_processed'],
  'publication_points_failed': report['tree']['instances_failed'],
  'vrps': len(report['vrps']),
  'aspas': len(report['aspas']),
}
Path(sys.argv[2]).write_text(json.dumps(meta, ensure_ascii=False, indent=2)+'\n', encoding='utf-8')
PY

  if [[ "$KEEP_DB" -eq 0 ]]; then
    rm -rf "$db_dir"
  fi
}

IFS=',' read -r -a RIRS <<< "$RIR_LIST"
for rir in "${RIRS[@]}"; do
  rir="$(echo "$rir" | xargs)"
  [[ -n "$rir" ]] || continue
  eval "$(python3 "$CASE_INFO_SCRIPT" --bundle-root "$BUNDLE_ROOT" --rir "$rir" --format env)"

  run_dir="$RUN_ROOT/${rir}_ccr_replay_${RUN_TAG}"
  mkdir -p "$run_dir"

  if [[ "$MODE" == "snapshot" || "$MODE" == "both" ]]; then
    run_one_mode \
      "$rir" snapshot "$run_dir" "$TRUST_ANCHOR" "$TAL_PATH" "$TA_PATH" \
      "$PAYLOAD_REPLAY_ARCHIVE" "$PAYLOAD_REPLAY_LOCKS" "$ROUTINATOR_BASE_RECORD_CSV" \
      "$PAYLOAD_DELTA_ARCHIVE" "$PAYLOAD_DELTA_LOCKS" "$ROUTINATOR_DELTA_RECORD_CSV" \
      "$SNAPSHOT_VALIDATION_TIME" "$DELTA_VALIDATION_TIME"
  fi
  if [[ "$MODE" == "delta" || "$MODE" == "both" ]]; then
    run_one_mode \
      "$rir" delta "$run_dir" "$TRUST_ANCHOR" "$TAL_PATH" "$TA_PATH" \
      "$PAYLOAD_REPLAY_ARCHIVE" "$PAYLOAD_REPLAY_LOCKS" "$ROUTINATOR_BASE_RECORD_CSV" \
      "$PAYLOAD_DELTA_ARCHIVE" "$PAYLOAD_DELTA_LOCKS" "$ROUTINATOR_DELTA_RECORD_CSV" \
      "$SNAPSHOT_VALIDATION_TIME" "$DELTA_VALIDATION_TIME"
  fi

  python3 - "$summary_json_tmp" "$run_dir" "$rir" "$MODE" <<'PY'
import json, sys
from pathlib import Path
summary_path = Path(sys.argv[1])
run_dir = Path(sys.argv[2])
rir = sys.argv[3]
mode = sys.argv[4]
rows = json.loads(summary_path.read_text(encoding='utf-8'))
for submode in ['snapshot','delta']:
    if mode not in ('both', submode):
        continue
    compare = run_dir / f'{rir}_{submode}_ccr_compare_summary.md'
    meta = run_dir / f'{rir}_{submode}_meta.json'
    verify = run_dir / f'{rir}_{submode}_ccr_verify.json'
    if not compare.exists() or not meta.exists() or not verify.exists():
        continue
    compare_text = compare.read_text(encoding='utf-8')
    meta_obj = json.loads(meta.read_text(encoding='utf-8'))
    verify_obj = json.loads(verify.read_text(encoding='utf-8'))
    def metric(name):
        prefix = f'| {name} | '
        for line in compare_text.splitlines():
            if line.startswith(prefix):
                return int(line.split('|')[2].strip())
        raise SystemExit(f'missing metric {name} in {compare}')
    rows.append({
        'rir': rir,
        'mode': submode,
        'run_dir': str(run_dir),
        'duration_seconds': meta_obj['duration_seconds'],
        'vrps': meta_obj['vrps'],
        'aspas': meta_obj['aspas'],
        'only_in_ours': metric('only_in_ours'),
        'only_in_record': metric('only_in_record'),
        'intersection': metric('intersection'),
        'state_hashes_ok': verify_obj.get('state_hashes_ok'),
    })
summary_path.write_text(json.dumps(rows, ensure_ascii=False, indent=2)+'\n', encoding='utf-8')
PY

done

python3 - "$summary_json_tmp" "$summary_json" "$summary_md" "$RUN_TAG" <<'PY'
import json, sys
from pathlib import Path
rows = json.loads(Path(sys.argv[1]).read_text(encoding='utf-8'))
out_json = Path(sys.argv[2])
out_md = Path(sys.argv[3])
run_tag = sys.argv[4]
out_json.write_text(json.dumps(rows, ensure_ascii=False, indent=2)+'\n', encoding='utf-8')
parts = []
parts.append('# Multi-RIR CCR Replay Verify Summary\n\n')
parts.append(f'- run_tag: `{run_tag}`\n\n')
parts.append('| rir | mode | duration_s | vrps | aspas | only_in_ours | only_in_record | state_hashes_ok |\n')
parts.append('|---|---|---:|---:|---:|---:|---:|---|\n')
for row in rows:
    parts.append(f"| {row['rir']} | {row['mode']} | {row['duration_seconds']} | {row['vrps']} | {row['aspas']} | {row['only_in_ours']} | {row['only_in_record']} | {row['state_hashes_ok']} |\n")
out_md.write_text(''.join(parts), encoding='utf-8')
PY

rm -f "$summary_json_tmp"

echo "== multi-rir replay verify complete ==" >&2
echo "- summary: $summary_md" >&2
echo "- summary json: $summary_json" >&2
