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

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

CASE_LIST=${CASE_LIST:-"${PROJECT_ROOT}/tools/feishu_project/cncap_case.txt"}
SYNC_ROOT=${SYNC_ROOT:-/data1/dongying/Mono3d/CNCAP/feishu_project}
EXPORT_JSON=${EXPORT_JSON:-"${SYNC_ROOT}/exports/cncap_case_issue_list.json"}
CASE_INDEX_JSON=${CASE_INDEX_JSON:-"${SYNC_ROOT}/exports/cncap_case_issue_index.json"}
DOWNLOAD_ROOT=${DOWNLOAD_ROOT:-"${SYNC_ROOT}/downloaded_issue_data"}
DOWNLOAD_MANIFEST_PATH=${DOWNLOAD_MANIFEST_PATH:-"${DOWNLOAD_ROOT}/download_manifest.json"}
INFERENCE_ROOT=${INFERENCE_ROOT:-"${SYNC_ROOT}/inference_issue_data"}
INFERENCE_MANIFEST_PATH=${INFERENCE_MANIFEST_PATH:-"${INFERENCE_ROOT}/inference_manifest.json"}

PYTHON_BIN=${PYTHON_BIN:-/deeplearning_team/ydong/dongying/miniconda/envs/dev/bin/python}
RUN_BUILD=${RUN_BUILD:-1}
RUN_DOWNLOAD=${RUN_DOWNLOAD:-1}
RUN_INFERENCE=${RUN_INFERENCE:-1}
ENABLE_TRACKING=${ENABLE_TRACKING:-1}
ENABLE_CONVERT=${ENABLE_CONVERT:-1}
ENABLE_VISUALIZE=${ENABLE_VISUALIZE:-0}
ENABLE_TEMPORAL_ANALYSIS=${ENABLE_TEMPORAL_ANALYSIS:-0}
SKIP_EXISTING_INFERENCE=${SKIP_EXISTING_INFERENCE:-1}
DRY_RUN=${DRY_RUN:-0}

USE_ISSUE_FRAME_WINDOW=${USE_ISSUE_FRAME_WINDOW:-0}
FRAME_BEFORE=${FRAME_BEFORE:-200}
FRAME_AFTER=${FRAME_AFTER:-200}
MISSING_ISSUE_FRAME_POLICY=${MISSING_ISSUE_FRAME_POLICY:-full}
FRAME_INDEX_START=${FRAME_INDEX_START:-}
FRAME_INDEX_END=${FRAME_INDEX_END:-}
FRAME_ID_START=${FRAME_ID_START:-}
FRAME_ID_END=${FRAME_ID_END:-}
TARGET_FRAME_ID=${TARGET_FRAME_ID:-}

VIDEO_STRIDE=${VIDEO_STRIDE:-1}
MAX_IMAGES=${MAX_IMAGES:-0}
EXPORTED_MODEL=${EXPORTED_MODEL:-${PROJECT_ROOT}/runs/export/train_mono3d_two_roi_20260416-raw_no_edge/merged_model.torchscript}
DEVICE=${DEVICE:-}
PROVIDERS=${PROVIDERS:-}
ENABLE_ATTR=${ENABLE_ATTR:-0}
ENABLE_CROSS_CLASS_MERGE_PRIOR=${ENABLE_CROSS_CLASS_MERGE_PRIOR:-1}
SAVE_AGGREGATE_PREDICTIONS=${SAVE_AGGREGATE_PREDICTIONS:-1}
INFERENCE_EXTRA_ARGS=${INFERENCE_EXTRA_ARGS:-}

TRACK_CLASSES=${TRACK_CLASSES:-0 1 2 3 4 5 6 7 8 9 10 11 12}
IOU_THRESH=${IOU_THRESH:-0.3}
MAX_AGE=${MAX_AGE:-5}
MIN_HITS=${MIN_HITS:-1}
DIST_THRESH=${DIST_THRESH:-100}
MAX_3D_DISTANCE=${MAX_3D_DISTANCE:-10.0}
MAX_FRAMES=${MAX_FRAMES:-}
MERGE_OUTPUT_NAME=${MERGE_OUTPUT_NAME:-combined_tracking.json}
FILE_PATTERN=${FILE_PATTERN:-*.json}
ENABLE_USE_3D=${ENABLE_USE_3D:-0}
CONVERT_OUTPUT_DIR_NAME=${CONVERT_OUTPUT_DIR_NAME:-objectlist}
CONVERT_TRACKING_JSON_NAME=${CONVERT_TRACKING_JSON_NAME:-merge.json}
CONVERT_CAM_ID=${CONVERT_CAM_ID:-}
VIS_DOWNLOAD_ROOT=${VIS_DOWNLOAD_ROOT:-"${DOWNLOAD_ROOT}"}
VIS_OUTPUT_ROOT=${VIS_OUTPUT_ROOT:-}
VIS_OUTPUT_DIR_NAME=${VIS_OUTPUT_DIR_NAME:-tracking_vis_raw}
VIS_TRACKING_JSON_NAME=${VIS_TRACKING_JSON_NAME:-merge.json}
VIS_MAX_FRAMES=${VIS_MAX_FRAMES:-}
VIS_CLASS_ID=${VIS_CLASS_ID:-}
VIS_TRACK_IDS=${VIS_TRACK_IDS:-}
VIS_SHOW_TRAJECTORY=${VIS_SHOW_TRAJECTORY:-0}
TEMPORAL_OUTPUT_ROOT=${TEMPORAL_OUTPUT_ROOT:-}
TEMPORAL_OUTPUT_DIR_NAME=${TEMPORAL_OUTPUT_DIR_NAME:-temporal_observation}
TEMPORAL_JSON_NAME=${TEMPORAL_JSON_NAME:-merge.json}
TEMPORAL_MIN_LENGTH=${TEMPORAL_MIN_LENGTH:-3}
TEMPORAL_TRACK_IDS=${TEMPORAL_TRACK_IDS:-}
TEMPORAL_CLASS_ID=${TEMPORAL_CLASS_ID:-}
TEMPORAL_FRAME_ID_START=${TEMPORAL_FRAME_ID_START:-}
TEMPORAL_FRAME_ID_END=${TEMPORAL_FRAME_ID_END:-}
TEMPORAL_PLOTS=${TEMPORAL_PLOTS:-0}
TEMPORAL_EXPORT_SERIES=${TEMPORAL_EXPORT_SERIES:-1}
TEMPORAL_FOCUS_TRACK_PLOTS=${TEMPORAL_FOCUS_TRACK_PLOTS:-1}
TEMPORAL_PREFER_EGO=${TEMPORAL_PREFER_EGO:-1}
TEMPORAL_X_AXIS=${TEMPORAL_X_AXIS:-frame_id}
TEMPORAL_HEADING_SOURCE=${TEMPORAL_HEADING_SOURCE:-camera_reg}
TRACKING_MODEL_VERSION=${TRACKING_MODEL_VERSION:-}

SKIP_MDI=${SKIP_MDI:-0}
SKIP_COPY=${SKIP_COPY:-0}
ONLY_REDOWNLOAD_AFFECTED_CASES=${ONLY_REDOWNLOAD_AFFECTED_CASES:-0}
ID_BASE=${ID_BASE:-9000000000}

CASE_JSON_BUILDER=${CASE_JSON_BUILDER:-"${PROJECT_ROOT}/tools/feishu_project/build_cncap_case_issue_json.py"}
DOWNLOAD_WRAPPER=${DOWNLOAD_WRAPPER:-"${PROJECT_ROOT}/tools/feishu_project/download_issue_data.sh"}
INFERENCE_WRAPPER=${INFERENCE_WRAPPER:-"${PROJECT_ROOT}/tools/feishu_project/run_issue_data_inference.sh"}
TRACKING_WRAPPER=${TRACKING_WRAPPER:-"${PROJECT_ROOT}/tools/feishu_project/run_issue_data_tracking.sh"}

ISSUE_ID_ARGS=()
ISSUE_ID_VALUES=()

show_usage() {
  cat <<EOF
Usage:
  bash $(basename "${BASH_SOURCE[0]}") [--issue-id <id>]...

Environment variables:
  CASE_LIST, SYNC_ROOT, EXPORT_JSON, CASE_INDEX_JSON
  DOWNLOAD_ROOT, INFERENCE_ROOT, EXPORTED_MODEL
  RUN_BUILD, RUN_DOWNLOAD, RUN_INFERENCE, ENABLE_TRACKING
  ENABLE_CONVERT, ENABLE_VISUALIZE, ENABLE_TEMPORAL_ANALYSIS
  DRY_RUN, ID_BASE
EOF
}

while (($# > 0)); do
  case "$1" in
    --issue-id)
      if (($# < 2)); then
        echo "Error: --issue-id requires a value" >&2
        exit 1
      fi
      ISSUE_ID_ARGS+=("$1" "$2")
      ISSUE_ID_VALUES+=("$2")
      shift 2
      ;;
    --issue-id=*)
      issue_id="${1#*=}"
      ISSUE_ID_ARGS+=("$1")
      ISSUE_ID_VALUES+=("${issue_id}")
      shift
      ;;
    -h|--help)
      show_usage
      exit 0
      ;;
    *)
      echo "Error: unsupported option: $1" >&2
      show_usage >&2
      exit 1
      ;;
  esac
done

print_stage() {
  local stage_name="$1"
  echo ""
  echo "######################################################################"
  echo "# ${stage_name}"
  echo "######################################################################"
}

resolve_tracking_model_version() {
  if [[ -n "${TRACKING_MODEL_VERSION}" ]]; then
    printf '%s\n' "${TRACKING_MODEL_VERSION}"
    return 0
  fi

  if [[ -n "${EXPORTED_MODEL}" ]] && [[ "${EXPORTED_MODEL}" =~ ([0-9]{8}) ]]; then
    printf '%s\n' "${BASH_REMATCH[1]}"
    return 0
  fi

  return 1
}

has_local_video_cases() {
  local search_root="$1"
  shift || true

  if [[ ! -d "${search_root}" ]]; then
    return 1
  fi

  if [[ "$#" -eq 0 ]]; then
    [[ -n "$(find "${search_root}" -type f -path '*/sigmastar.1/camera4.bin' -print -quit)" ]]
    return
  fi

  local issue_id=""
  for issue_id in "$@"; do
    if [[ -d "${search_root}/issue_${issue_id}" ]] && [[ -n "$(find "${search_root}/issue_${issue_id}" -type f -path '*/sigmastar.1/camera4.bin' -print -quit)" ]]; then
      return 0
    fi
  done
  return 1
}

TMP_ROOT=""
EFFECTIVE_EXPORT_JSON="${EXPORT_JSON}"
EFFECTIVE_CASE_INDEX_JSON="${CASE_INDEX_JSON}"

cleanup() {
  if [[ -n "${TMP_ROOT}" && -d "${TMP_ROOT}" ]]; then
    rm -rf "${TMP_ROOT}"
  fi
}
trap cleanup EXIT

if [[ "${DRY_RUN}" == "1" && "${RUN_BUILD}" == "1" ]]; then
  TMP_ROOT=$(mktemp -d /tmp/cncap_case_pipeline.XXXXXX)
  EFFECTIVE_EXPORT_JSON="${TMP_ROOT}/cncap_case_issue_list.json"
  EFFECTIVE_CASE_INDEX_JSON="${TMP_ROOT}/cncap_case_issue_index.json"
fi

export PYTHON_BIN
export TRACK_CLASSES
export IOU_THRESH
export MAX_AGE
export MIN_HITS
export DIST_THRESH
export MAX_3D_DISTANCE
export MAX_FRAMES
export MERGE_OUTPUT_NAME
export FILE_PATTERN
export ENABLE_USE_3D
export ENABLE_CONVERT
export ENABLE_VISUALIZE
export ENABLE_TEMPORAL_ANALYSIS
export CONVERT_OUTPUT_DIR_NAME
export CONVERT_TRACKING_JSON_NAME
export CONVERT_CAM_ID
export VIS_DOWNLOAD_ROOT
export VIS_OUTPUT_ROOT
export VIS_OUTPUT_DIR_NAME
export VIS_TRACKING_JSON_NAME
export VIS_MAX_FRAMES
export VIS_CLASS_ID
export VIS_TRACK_IDS
export VIS_SHOW_TRAJECTORY
export TEMPORAL_OUTPUT_ROOT
export TEMPORAL_OUTPUT_DIR_NAME
export TEMPORAL_JSON_NAME
export TEMPORAL_MIN_LENGTH
export TEMPORAL_TRACK_IDS
export TEMPORAL_CLASS_ID
export TEMPORAL_FRAME_ID_START
export TEMPORAL_FRAME_ID_END
export TEMPORAL_PLOTS
export TEMPORAL_EXPORT_SERIES
export TEMPORAL_FOCUS_TRACK_PLOTS
export TEMPORAL_PREFER_EGO
export TEMPORAL_X_AXIS
export TEMPORAL_HEADING_SOURCE

if [[ "${RUN_BUILD}" == "1" ]]; then
  print_stage "Build CNCAP Synthetic Issue JSON"
  echo "CASE_LIST         : ${CASE_LIST}"
  echo "EXPORT_JSON       : ${EFFECTIVE_EXPORT_JSON}"
  echo "CASE_INDEX_JSON   : ${EFFECTIVE_CASE_INDEX_JSON}"
  echo "ID_BASE           : ${ID_BASE}"

  "${PYTHON_BIN}" "${CASE_JSON_BUILDER}" \
    --input "${CASE_LIST}" \
    --output "${EFFECTIVE_EXPORT_JSON}" \
    --case-index-output "${EFFECTIVE_CASE_INDEX_JSON}" \
    --id-base "${ID_BASE}"
elif [[ ! -f "${EFFECTIVE_EXPORT_JSON}" ]]; then
  echo "Error: export json does not exist and RUN_BUILD=0: ${EFFECTIVE_EXPORT_JSON}" >&2
  exit 1
fi

if [[ "${RUN_DOWNLOAD}" == "1" ]]; then
  print_stage "Download CNCAP Case Data"
  INPUT_JSON="${EFFECTIVE_EXPORT_JSON}" \
    OUTPUT_ROOT="${DOWNLOAD_ROOT}" \
    MANIFEST_PATH="${DOWNLOAD_MANIFEST_PATH}" \
    PYTHON_BIN="${PYTHON_BIN}" \
    DRY_RUN="${DRY_RUN}" \
    SKIP_MDI="${SKIP_MDI}" \
    SKIP_COPY="${SKIP_COPY}" \
    ONLY_REDOWNLOAD_AFFECTED_CASES="${ONLY_REDOWNLOAD_AFFECTED_CASES}" \
    bash "${DOWNLOAD_WRAPPER}" "${ISSUE_ID_ARGS[@]}"
fi

if [[ "${RUN_INFERENCE}" == "1" ]]; then
  if [[ "${DRY_RUN}" == "1" ]] && ! has_local_video_cases "${DOWNLOAD_ROOT}" "${ISSUE_ID_VALUES[@]}"; then
    print_stage "Skip CNCAP Inference"
    echo "Skipping inference in dry-run because no local downloaded camera4.bin cases were found."
    echo "Run download without DRY_RUN first, or reuse an existing DOWNLOAD_ROOT to plan inference."
  else
    print_stage "Run CNCAP Inference"
    DOWNLOAD_ROOT="${DOWNLOAD_ROOT}" \
      OUTPUT_ROOT="${INFERENCE_ROOT}" \
      MANIFEST_PATH="${INFERENCE_MANIFEST_PATH}" \
      PYTHON_BIN="${PYTHON_BIN}" \
      ISSUE_JSON="${EFFECTIVE_EXPORT_JSON}" \
      VIDEO_STRIDE="${VIDEO_STRIDE}" \
      MAX_IMAGES="${MAX_IMAGES}" \
      FRAME_INDEX_START="${FRAME_INDEX_START}" \
      FRAME_INDEX_END="${FRAME_INDEX_END}" \
      FRAME_ID_START="${FRAME_ID_START}" \
      FRAME_ID_END="${FRAME_ID_END}" \
      TARGET_FRAME_ID="${TARGET_FRAME_ID}" \
      FRAME_BEFORE="${FRAME_BEFORE}" \
      FRAME_AFTER="${FRAME_AFTER}" \
      USE_ISSUE_FRAME_WINDOW="${USE_ISSUE_FRAME_WINDOW}" \
      MISSING_ISSUE_FRAME_POLICY="${MISSING_ISSUE_FRAME_POLICY}" \
      EXPORTED_MODEL="${EXPORTED_MODEL}" \
      DEVICE="${DEVICE}" \
      PROVIDERS="${PROVIDERS}" \
      ENABLE_ATTR="${ENABLE_ATTR}" \
      ENABLE_CROSS_CLASS_MERGE_PRIOR="${ENABLE_CROSS_CLASS_MERGE_PRIOR}" \
      SAVE_AGGREGATE_PREDICTIONS="${SAVE_AGGREGATE_PREDICTIONS}" \
      SKIP_EXISTING="${SKIP_EXISTING_INFERENCE}" \
      DRY_RUN="${DRY_RUN}" \
      ENABLE_TRACKING=0 \
      INFERENCE_EXTRA_ARGS="${INFERENCE_EXTRA_ARGS}" \
      bash "${INFERENCE_WRAPPER}" "${ISSUE_ID_ARGS[@]}"
  fi
fi

if [[ "${ENABLE_TRACKING}" != "1" ]]; then
  exit 0
fi

if [[ "${DRY_RUN}" == "1" ]]; then
  print_stage "Skip CNCAP Tracking"
  echo "Skipping tracking because DRY_RUN=1."
  exit 0
fi

TRACKING_MODEL_VERSION_RESOLVED=$(resolve_tracking_model_version || true)

print_stage "Run CNCAP Tracking/Convert Workflow"
echo "INFERENCE_ROOT          : ${INFERENCE_ROOT}"
echo "VIS_DOWNLOAD_ROOT       : ${VIS_DOWNLOAD_ROOT}"
if [[ -n "${TRACKING_MODEL_VERSION_RESOLVED}" ]]; then
  echo "TRACKING_MODEL_VERSION  : ${TRACKING_MODEL_VERSION_RESOLVED}"
fi

RESULTS_ROOT="${INFERENCE_ROOT}" \
  PYTHON_BIN="${PYTHON_BIN}" \
  TRACKING_MODEL_VERSION="${TRACKING_MODEL_VERSION_RESOLVED}" \
  bash "${TRACKING_WRAPPER}" "${INFERENCE_ROOT}" "${ISSUE_ID_ARGS[@]}"
