#!/usr/bin/env bash
# Download shared dev content from Dropbox under 4-Board Test Fixture — NOT positions 1–4.
#
# Run on Raspberry Pi (Bookworm) — same rclone remote as sync_to_dropbox.sh.
# This script lives under sync/ and is updated by its own pull.
#
# Usage:
#   cd ~/EtherGold/sync
#   cp rclone.env.example rclone.env
#   cp fixture_bridge.env.example ~/EtherGold/fixture-bridge.env
#   nano ~/EtherGold/fixture-bridge.env   # FIXTURE_POS=1..4, FIXTURE_MODE=debug
#   DRY_RUN=1 bash pull_fixture_shared_from_dropbox.sh
#   bash pull_fixture_shared_from_dropbox.sh
#
# Preferred unified pull (EtherGold + DyzineFrame):
#   bash pull_all_from_dropbox.sh
#   bash pull_from_dropbox.sh   # alias
#
# Flat layout (2026-07 restructure — no mirror):
#   Pull lands directly at ~/EtherGold/dev (runtime) and ~/EtherGold/sync (scripts).
#   Remote whitelist = dev/** + sync/** (see fixture_timing.rclone-filter).
#   PC-only trees (logs/1-5, workspace sessions/, dev/_archive, prod/) are never pulled.
#
# PULL_SCOPE (default timing):
#   timing  — dev/** + sync/** (flat runtime + dev/test tools)
#   full    — PC only (includes sessions/ archives)
#
# Pull destination is LOCAL_FIXTURE_ROOT (default: ~/EtherGold).

if grep -q $'\r' "${BASH_SOURCE[0]}" 2>/dev/null; then
  sed -i 's/\r$//' "${BASH_SOURCE[0]}"
  exec bash "${BASH_SOURCE[0]}" "$@"
fi

set -euo pipefail

if [[ "$(id -un)" == root ]]; then
  echo "FATAL: do not run pull as root/sudo." >&2
  echo "  rclone config lives under ~topbox, not /root." >&2
  echo "  cd ~/EtherGold/sync && bash pull_fixture_shared_from_dropbox.sh" >&2
  exit 1
fi

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ENV_FILE="${ROOT}/rclone.env"
PATHS="${ROOT}/dropbox_paths.sh"

if [[ -f "${ROOT}/ethergold_paths.sh" ]]; then
  # shellcheck source=ethergold_paths.sh
  source "${ROOT}/ethergold_paths.sh"
fi
ETHERGOLD_ROOT="${ETHERGOLD_ROOT:-/home/topbox/EtherGold}"
ETHERGOLD_DEV="${ETHERGOLD_DEV:-${ETHERGOLD_ROOT}/dev}"

if [[ ! -f "${ENV_FILE}" ]]; then
  echo "Missing ${ENV_FILE}" >&2
  echo "Copy rclone.env.example to rclone.env and set RCLONE_REMOTE + DROPBOX_FIXTURE_ROOT." >&2
  exit 1
fi

if grep -q $'\r' "${ENV_FILE}" 2>/dev/null; then
  sed -i 's/\r$//' "${ENV_FILE}" 2>/dev/null || tr -d '\r' < "${ENV_FILE}" > "${ENV_FILE}.tmp" && mv "${ENV_FILE}.tmp" "${ENV_FILE}"
fi

# shellcheck source=/dev/null
source "${ENV_FILE}"

if [[ -f "${PATHS}" ]]; then
  # shellcheck source=dropbox_paths.sh
  source "${PATHS}"
fi

migrate_legacy_dropbox_paths() {
  [[ -n "${DROPBOX_FIXTURE_ROOT_CANON:-}" ]] || return 0
  local changed=0
  # Hardware-Dev → OHD workspace (pre-2026-06-15)
  if [[ -n "${DROPBOX_FIXTURE_ROOT_LEGACY:-}" ]] \
    && grep -qF "${DROPBOX_FIXTURE_ROOT_LEGACY}" "${ENV_FILE}" 2>/dev/null; then
    sed -i "s|${DROPBOX_FIXTURE_ROOT_LEGACY}|${DROPBOX_FIXTURE_ROOT_CANON}|g" "${ENV_FILE}"
    echo "pull: migrated Dropbox path (Hardware Dev → OHD workspace)"
    changed=1
  fi
  # Flat restructure (pre-2026-07-08): .../EtherGold/4-Board Test Fixture → .../EtherGold
  if [[ -n "${DROPBOX_FIXTURE_ROOT_LEGACY_OHD:-}" ]] \
    && grep -qF "${DROPBOX_FIXTURE_ROOT_LEGACY_OHD}" "${ENV_FILE}" 2>/dev/null; then
    sed -i "s|${DROPBOX_FIXTURE_ROOT_LEGACY_OHD}|${DROPBOX_FIXTURE_ROOT_CANON}|g" "${ENV_FILE}"
    echo "pull: migrated Dropbox path (4-Board Test Fixture → flat EtherGold)"
    changed=1
  fi
  # Catch-all: strip a stale trailing '/4-Board Test Fixture' from either key.
  if grep -qE '/4-Board Test Fixture(/[1-5])?"?$' "${ENV_FILE}" 2>/dev/null; then
    sed -i -E 's|/4-Board Test Fixture(/[1-5])?("?)$|\1\2|' "${ENV_FILE}"
    echo "pull: stripped stale '/4-Board Test Fixture' from remote root"
    changed=1
  fi
  # Workshop tip → To Deploy/EtherGold (2026-07-22)
  if [[ -n "${DROPBOX_FIXTURE_ROOT_LEGACY_WORKSHOP:-}" ]] \
    && [[ -n "${DROPBOX_FIXTURE_ROOT_CANON:-}" ]] \
    && grep -qF "DROPBOX_FIXTURE_ROOT=\"${DROPBOX_FIXTURE_ROOT_LEGACY_WORKSHOP}\"" "${ENV_FILE}" 2>/dev/null; then
    sed -i "s|DROPBOX_FIXTURE_ROOT=\"${DROPBOX_FIXTURE_ROOT_LEGACY_WORKSHOP}\"|DROPBOX_FIXTURE_ROOT=\"${DROPBOX_FIXTURE_ROOT_CANON}\"|" "${ENV_FILE}"
    changed=1
    echo "pull: migrated DROPBOX_FIXTURE_ROOT (workshop EtherGold → To Deploy/EtherGold)"
  fi
  # Also migrate bare path without requiring exact quoting form
  if [[ -n "${DROPBOX_FIXTURE_ROOT_LEGACY_WORKSHOP:-}" ]] \
    && grep -qF "${DROPBOX_FIXTURE_ROOT_LEGACY_WORKSHOP}\"" "${ENV_FILE}" 2>/dev/null \
    && ! grep -qF "To Deploy/EtherGold" "${ENV_FILE}" 2>/dev/null; then
    # Avoid rewriting DROPBOX_DEST=.../EtherGold/logs/N
    if grep -qE '^DROPBOX_FIXTURE_ROOT=.*Cursor OHD Project/EtherGold"$' "${ENV_FILE}" 2>/dev/null; then
      sed -i 's|^DROPBOX_FIXTURE_ROOT="\(.*\)/Cursor OHD Project/EtherGold"|DROPBOX_FIXTURE_ROOT="\1/Cursor OHD Project/To Deploy/EtherGold"|' "${ENV_FILE}"
      changed=1
      echo "pull: migrated DROPBOX_FIXTURE_ROOT → To Deploy/EtherGold"
    fi
  fi
  # install_sync once derived DEST from FIXTURE_ROOT → wrongly landed under To Deploy/logs.
  if grep -qE '^DROPBOX_DEST=.*To Deploy/EtherGold/logs/' "${ENV_FILE}" 2>/dev/null; then
    sed -i 's|To Deploy/EtherGold/logs/|EtherGold/logs/|g' "${ENV_FILE}"
    changed=1
    echo "pull: migrated DROPBOX_DEST (To Deploy/logs → workshop EtherGold/logs)"
  fi
  if [[ "${changed}" == "1" ]]; then
    # shellcheck source=/dev/null
    source "${ENV_FILE}"
  fi
}
migrate_legacy_dropbox_paths

validate_fixture_remote() {
  case "${FIXTURE_REMOTE}" in
    */fixture-timing)
      echo "FATAL: DROPBOX_FIXTURE_ROOT must be the 4-Board Test Fixture folder," >&2
      echo "  not fixture-timing. Fix rclone.env (see dropbox_paths.sh)." >&2
      exit 1
      ;;
    *"/Legacy Code"|*"/Legacy Code/"*)
      echo "FATAL: DROPBOX_FIXTURE_ROOT points at Legacy Code — wrong tree." >&2
      exit 1
      ;;
  esac
  if [[ "${PULL_SCOPE}" == "timing" ]] && [[ ! -f "${ROOT}/fixture_timing.rclone-filter" ]]; then
    echo "FATAL: missing whitelist filter ${ROOT}/fixture_timing.rclone-filter" >&2
    exit 1
  fi
}

purge_forbidden_pi_trees() {
  # Flat layout: stale pre-restructure trees are harmless as long as you run from
  # ~/EtherGold/dev (its own sys.path), so we do NOT auto-delete. Some of these dirs
  # (e.g. Daemon/) may back a field systemd unit on shared office Pis. WARN only.
  # To remove them deliberately: PURGE_STALE=1 bash pull_fixture_shared_from_dropbox.sh
  local -a stale=(
    "${ETHERGOLD_ROOT}/bridge"
    "${ETHERGOLD_ROOT}/Daemon"
    "${ETHERGOLD_ROOT}/4-Board Test Fixture"
    "${ETHERGOLD_ROOT}/fixture-timing"
  )
  local found=0
  for d in "${stale[@]}"; do
    [[ -e "${d}" ]] || continue
    found=1
    if [[ "${PURGE_STALE:-0}" == "1" ]]; then
      echo "PURGE_STALE=1 — removing stale pre-restructure tree: ${d}"
      rm -rf "${d}"
    else
      echo "NOTE: stale pre-restructure tree present (not used by flat dev/): ${d}"
    fi
  done
  if [[ "${found}" == "1" && "${PURGE_STALE:-0}" != "1" ]]; then
    echo "  (harmless if you run from ~/EtherGold/dev. PURGE_STALE=1 to delete — check field ethergold.service first.)"
  fi
}

PULL_SCOPE="${PULL_SCOPE:-timing}"
if [[ "${PULL_SCOPE}" != "timing" ]]; then
  echo "WARN: PULL_SCOPE=${PULL_SCOPE} — field Pis should use timing (whitelist, no Legacy Code)" >&2
fi
case "${PULL_SCOPE}" in
  timing)
    FILTER_FILE="${ROOT}/fixture_timing.rclone-filter"
    SCOPE_DESC="fixture-timing/** + sync/** (excludes sessions/, 1–4/)"
    ;;
  shared)
    FILTER_FILE="${ROOT}/fixture_shared.rclone-filter"
    SCOPE_DESC="fixture root except 1–4/ and sessions/"
    ;;
  full)
    FILTER_FILE="${ROOT}/fixture_full.rclone-filter"
    SCOPE_DESC="fixture root except 1–4/ (includes sessions/)"
    ;;
  *)
    echo "Unknown PULL_SCOPE=${PULL_SCOPE} (use timing, shared, or full)" >&2
    exit 1
    ;;
esac

if [[ ! -f "${FILTER_FILE}" ]]; then
  echo "Missing ${FILTER_FILE}" >&2
  exit 1
fi

if ! command -v rclone >/dev/null 2>&1; then
  echo "rclone not found. Run: ${ROOT}/setup_rclone.sh" >&2
  exit 1
fi

RCLONE_REMOTE="${RCLONE_REMOTE:?Set RCLONE_REMOTE in rclone.env}"

if [[ -n "${DROPBOX_FIXTURE_ROOT:-}" ]]; then
  FIXTURE_REMOTE="${DROPBOX_FIXTURE_ROOT}"
elif [[ -n "${DROPBOX_DEST:-}" ]]; then
  FIXTURE_REMOTE="${DROPBOX_DEST%/}"
  FIXTURE_REMOTE="${FIXTURE_REMOTE%/*}"
  if [[ "${FIXTURE_REMOTE}" == "${DROPBOX_DEST%/}" ]]; then
    echo "Set DROPBOX_FIXTURE_ROOT in rclone.env (parent of positions 1–4)." >&2
    exit 1
  fi
elif [[ -n "${DROPBOX_FIXTURE_ROOT_CANON:-}" ]]; then
  FIXTURE_REMOTE="${DROPBOX_FIXTURE_ROOT_CANON}"
  echo "Using canonical DROPBOX_FIXTURE_ROOT from dropbox_paths.sh"
else
  echo "Set DROPBOX_FIXTURE_ROOT in rclone.env" >&2
  exit 1
fi

# Flat layout: pull lands directly under ~/EtherGold. The whitelist filter selects
# remote dev/** + sync/**, so files land at ~/EtherGold/dev and ~/EtherGold/sync.
FIXTURE_ROOT="${LOCAL_FIXTURE_ROOT:-${ETHERGOLD_ROOT}}"
mkdir -p "${FIXTURE_ROOT}"

validate_fixture_remote

REMOTE_PATH="${RCLONE_REMOTE}:${FIXTURE_REMOTE}"
DRY_RUN="${DRY_RUN:-0}"
VERBOSE="${VERBOSE:-1}"
if [[ "${QUIET:-0}" == "1" ]]; then
  VERBOSE=0
fi

RCLONE_ARGS=(
  --filter-from "${FILTER_FILE}"
  --create-empty-src-dirs
  --stats 5s
  --stats-one-line
)

if [[ "${VERBOSE}" == "1" ]]; then
  RCLONE_ARGS+=(-v --progress)
else
  RCLONE_ARGS+=(--log-level "${RCLONE_LOG_LEVEL:-NOTICE}")
  echo "Tip: QUIET=0 or VERBOSE=1 to list each transferred file."
  echo ""
fi

if [[ "${DRY_RUN}" == "1" ]]; then
  RCLONE_ARGS+=(--dry-run)
  echo "DRY RUN — nothing will be downloaded."
  echo ""
fi

echo "Remote:      ${REMOTE_PATH}"
echo "Local:       ${FIXTURE_ROOT}"
echo "Sync dir:    ${ROOT}"
echo "PULL_SCOPE:  ${PULL_SCOPE} — ${SCOPE_DESC}"
echo "Filter:      ${FILTER_FILE} (whitelist — no Legacy Code)"
head -n 3 "${FILTER_FILE}" | sed 's/^/  /'
echo ""

_rclone_extra=()
if [[ "${DRY_RUN}" == "1" ]]; then
  _rclone_extra+=(--dry-run)
fi
if [[ "${VERBOSE}" == "1" ]]; then
  _rclone_extra+=(-v)
fi

# Field Pis run pull from ~/EtherGold/sync but may have a stale local filter (blocks new sync/*.sh).
if [[ "${PULL_SCOPE}" == "timing" ]] && [[ -f "${FILTER_FILE}" ]]; then
  echo "Bootstrap: refresh fixture_timing.rclone-filter from remote → ${ROOT}"
  rclone copy "${REMOTE_PATH}/sync/fixture_timing.rclone-filter" "${ROOT}/" "${_rclone_extra[@]}"
fi

rclone copy "${REMOTE_PATH}" "${FIXTURE_ROOT}" "${RCLONE_ARGS[@]}"

echo ""
if [[ "${DRY_RUN}" == "1" ]]; then
  echo "Dry run complete. Re-run without DRY_RUN=1 to download."
  exit 0
fi

echo "Done. Updated under: ${FIXTURE_ROOT}"

purge_forbidden_pi_trees

pull_active_sync_dir() {
  # Flat layout: sync lands at ~/EtherGold/sync (== ROOT when launched there). If pull
  # was launched from a different sync copy, refresh that dir too.
  if [[ "${ROOT}" == "${FIXTURE_ROOT}/sync" ]]; then
    return 0
  fi
  echo "Refresh sync/ scripts → ${ROOT} (excludes rclone.env)"
  rclone copy "${REMOTE_PATH}/sync/" "${ROOT}/" -v --exclude rclone.env
  chmod a+x "${ROOT}/"*.sh 2>/dev/null || true
}
pull_active_sync_dir

seed_fixture_bridge_env() {
  local dest="${ETHERGOLD_ROOT}/fixture-bridge.env"
  local example="${ROOT}/fixture_bridge.env.example"
  [[ -f "${example}" ]] || return 0
  if [[ -f "${dest}" ]]; then
    echo "fixture-bridge.env exists: ${dest}"
    return 0
  fi
  cp "${example}" "${dest}"
  local pos=""
  case "$(hostname -s 2>/dev/null || hostname)" in
    topbox1) pos=1 ;;
    topbox2) pos=2 ;;
    topbox3) pos=3 ;;
    topbox4) pos=4 ;;
    topbox5) pos=5 ;;
  esac
  if [[ -n "${pos}" ]]; then
    sed -i "s/^FIXTURE_POS=.*/FIXTURE_POS=${pos}/" "${dest}"
    sed -i "s/^PI_LABEL=.*/PI_LABEL=topbox${pos}/" "${dest}"
  fi
  echo "Created ${dest} — edit FIXTURE_POS if hostname detection was wrong."
}

if [[ "${SKIP_INSTALL_SYNC:-0}" != "1" ]]; then
  echo ""
  echo "Post-pull: normalize, install_sync, seed fixture-bridge.env..."
  bash "${ROOT}/pi_normalize.sh"
  bash "${ROOT}/install_sync.sh"
  seed_fixture_bridge_env

  echo ""
  echo "Flat layout ready (no mirror): cd ${ETHERGOLD_DEV}"
  echo "  bench bridge: CHANNEL=both FIXTURE_POS=N ./run_bridge_jun11_good.sh"
  if [[ -f "${ROOT}/show_fixture_layout.sh" ]]; then
    bash "${ROOT}/show_fixture_layout.sh"
  fi
fi

echo ""
echo "PC-only (never pulled to Pi): logs/1-5 capture landing, workspace sessions/, dev/_archive, prod/"
