#!/bin/bash
# Cross-dataset eval for all 4 routes × 2 targets × 3 seeds = 24 runs.
# Source: CICIoT2023 (where all models were trained).
# Targets: CICIDS2017 + CICDDoS2019.

set -e
ROOT=/home/chy/mambafortrafficmodeling
UNIFIED_EVAL=${ROOT}/artifacts/verify_2026_04_24/eval_phase2_cross_cicddos2019.py
MIXED_EVAL=${ROOT}/Mixed_CFM/eval_cross.py
CROSS_DIR=${ROOT}/artifacts/route_comparison/cross
mkdir -p ${CROSS_DIR}

# Target dataset paths
declare -A TARGETS
TARGETS[cicids2017_store]=${ROOT}/datasets/cicids2017/processed/full_store
TARGETS[cicids2017_flows]=${ROOT}/datasets/cicids2017/processed/flows.parquet
TARGETS[cicids2017_features]=${ROOT}/datasets/cicids2017/processed/flow_features.parquet
TARGETS[cicids2017_features_spectral]=${ROOT}/datasets/cicids2017/processed/flow_features_spectral.parquet

TARGETS[cicddos2019_store]=${ROOT}/datasets/cicddos2019/processed/full_store
TARGETS[cicddos2019_flows]=${ROOT}/datasets/cicddos2019/processed/flows.parquet
TARGETS[cicddos2019_features]=${ROOT}/datasets/cicddos2019/processed/flow_features.parquet
TARGETS[cicddos2019_features_spectral]=${ROOT}/datasets/cicddos2019/processed/flow_features_spectral.parquet

run_unified_eval() {
  local gpu=$1 model_dir=$2 target=$3 features=$4 out_name=$5
  local out=${CROSS_DIR}/${out_name}.json
  [ -f "${out}" ] && { echo "[skip] ${out_name}"; return; }
  echo "[gpu${gpu} eval] ${out_name}"
  cd ${ROOT}/Unified_CFM
  CUDA_VISIBLE_DEVICES=${gpu} stdbuf -oL uv run --no-sync python -u ${UNIFIED_EVAL} \
    --model-dir ${model_dir} \
    --target-store ${TARGETS[${target}_store]} \
    --target-flows ${TARGETS[${target}_flows]} \
    --target-flow-features ${features} \
    --out ${out} \
    --n-benign 10000 --n-attack 10000 --seed 42 \
    --T 64 --batch-size 256 --n-steps 16 \
    > ${CROSS_DIR}/${out_name}.log 2>&1
}

run_mixed_eval() {
  local gpu=$1 model_dir=$2 target=$3 out_name=$4
  local out=${CROSS_DIR}/${out_name}.json
  [ -f "${out}" ] && { echo "[skip] ${out_name}"; return; }
  echo "[gpu${gpu} mixed eval] ${out_name}"
  cd ${ROOT}/Mixed_CFM
  CUDA_VISIBLE_DEVICES=${gpu} stdbuf -oL uv run --no-sync python -u ${MIXED_EVAL} \
    --model-dir ${model_dir} \
    --target-store ${TARGETS[${target}_store]} \
    --target-flows ${TARGETS[${target}_flows]} \
    --target-flow-features ${TARGETS[${target}_features]} \
    --out ${out} \
    --n-benign 10000 --n-attack 10000 --seed 42 \
    --T 64 --batch-size 256 --n-steps 16 \
    > ${CROSS_DIR}/${out_name}.log 2>&1
}

# === GPU 0 chain: baselines + route_a, both targets ===
{
for prefix_route in "baseline_ciciot2023:baseline" "route_a_causal_ciciot2023:route_a_causal"; do
  prefix=${prefix_route%:*}
  short=${prefix_route#*:}
  for seed in 42 43 44; do
    md=${ROOT}/artifacts/route_comparison/${prefix}_seed${seed}
    [ -f "${md}/model.pt" ] || continue
    for target in cicids2017 cicddos2019; do
      run_unified_eval 0 "${md}" "${target}" "${TARGETS[${target}_features]}" \
        "${short}_seed${seed}_to_${target}"
    done
  done
done
echo "[gpu0 cross chain done]"
} > /tmp/cross_gpu0.log 2>&1 &
GPU0=$!

# === GPU 1 chain: route_b (uses spectral features) + route_c (mixed) ===
{
# route_b: must use flow_features_spectral.parquet
for seed in 42 43 44; do
  md=${ROOT}/artifacts/route_comparison/route_b_spectral_ciciot2023_seed${seed}
  [ -f "${md}/model.pt" ] || continue
  for target in cicids2017 cicddos2019; do
    run_unified_eval 1 "${md}" "${target}" "${TARGETS[${target}_features_spectral]}" \
      "route_b_spectral_seed${seed}_to_${target}"
  done
done

# route_c: Mixed_CFM eval (uses canonical flow_features)
for seed in 42 43 44; do
  md=${ROOT}/artifacts/route_comparison/route_c_mixed_ciciot2023_seed${seed}
  [ -f "${md}/model.pt" ] || continue
  for target in cicids2017 cicddos2019; do
    run_mixed_eval 1 "${md}" "${target}" \
      "route_c_mixed_seed${seed}_to_${target}"
  done
done
echo "[gpu1 cross chain done]"
} > /tmp/cross_gpu1.log 2>&1 &
GPU1=$!

wait $GPU0
wait $GPU1
echo "[all cross done]"
ls -la ${CROSS_DIR}/*.json | wc -l
