#!/usr/bin/env bash
# Convert a bench hop/witness Pi to production stock (Michigan Atlas TopBox).
#
# Default keeps office wlan0 Wi-Fi so the unit stays SSH-reachable.
# Pass --strip-wifi only after HDMI QR is confirmed (unit drops off 10.1.10.x).
#
# Usage (on the Pi):
#   sudo bash prepare_listen_stock.sh
#   sudo bash prepare_listen_stock.sh --keep-office-wifi   # explicit default
#   sudo bash prepare_listen_stock.sh --strip-wifi
#
# Refuses fixture pos1-5 hostnames/IPs. Does not disable the wlan1 driver.
# Does not start DyzineFrame (no SSH restart). Autostart left ON for first-boot QR.
# Stamps ETHERGOLD_ROLE=listen (POG422 tap only, never inject/drive the bus).
# Collector + HTTP :31234 enabled on boot (inject=0). DF first-boot QR stays on.
# listen_ohd is Atlas TopBox TBX 1920x1080 (logos, progressive, ads, fireworks, door/error).
# OHD 3840x1080 is a Win11 overhead — use listen_ohd_server (headless HTTP) for that.
# Seeds latest DyzineFrame from Dropbox when those scripts are present.

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 [[ "${EUID}" -ne 0 ]]; then
  echo "FATAL: run with sudo" >&2
  exit 1
fi

STRIP_WIFI=0
for arg in "$@"; do
  case "${arg}" in
    --strip-wifi) STRIP_WIFI=1 ;;
    --keep-office-wifi) STRIP_WIFI=0 ;;
    -h|--help)
      sed -n '2,16p' "${BASH_SOURCE[0]}"
      exit 0
      ;;
    *)
      echo "FATAL: unknown arg ${arg}" >&2
      exit 1
      ;;
  esac
done

REAL_USER="${SUDO_USER:-topbox}"
HOME_TB="/home/${REAL_USER}"
HN="$(hostname | tr -d '\r')"
WLAN0_IP="$(ip -4 -br addr show wlan0 2>/dev/null | awk '{print $3}' | cut -d/ -f1 || true)"

# Office fixture pos1–5 are NEVER listen stock (current + former admin IPs).
# W2 10.1.10.140 is a witness — not pos5 (pos5 is .141).
is_fixture_seat() {
  case "${HN}" in
    topbox1|topbox2|topbox3|topbox4|topbox5) return 0 ;;
  esac
  case "${WLAN0_IP}" in
    10.1.10.229|10.1.10.110| \
    10.1.10.104|10.1.10.196| \
    10.1.10.232|10.1.10.187| \
    10.1.10.208|10.1.10.39| \
    10.1.10.141|10.1.10.45) return 0 ;;
  esac
  return 1
}

if is_fixture_seat; then
  echo "FATAL: refuse fixture seat hostname=${HN} wlan0=${WLAN0_IP}" >&2
  exit 1
fi

EDGEF="/etc/ethergold/edge.env"
if [[ ! -f "${EDGEF}" ]]; then
  EDGEF="/etc/fixture/edge.env"
fi
if [[ -f "${EDGEF}" ]] && grep -qE '^EDGE_MODE=1' "${EDGEF}" 2>/dev/null; then
  echo "FATAL: EDGE_MODE=1 on ${EDGEF} — not listen-stock (leave pos5/EDGE alone)" >&2
  exit 1
fi

MAC0="$(cat /sys/class/net/wlan0/address 2>/dev/null || echo unknown)"
ETH1="$(cat /sys/class/net/eth1/address 2>/dev/null || echo none)"
echo "=== prepare_listen_stock host=${HN} wlan0=${WLAN0_IP} mac=${MAC0} eth1=${ETH1} strip_wifi=${STRIP_WIFI} ==="

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [[ -f "${SCRIPT_DIR}/ethergold_field_env.sh" ]]; then
  # shellcheck source=ethergold_field_env.sh
  source "${SCRIPT_DIR}/ethergold_field_env.sh"
else
  ETHERGOLD_ETC=/etc/ethergold
  ETHERGOLD_VAR=/var/lib/ethergold
  ETHERGOLD_UNIT=ethergold.service
  ETHERGOLD_UNIT_LEGACY=fixture-prod.service
  ETHERGOLD_COLLECTOR_UNIT=ethergold-collector.service
  ETHERGOLD_COLLECTOR_UNIT_LEGACY=fixture-collector.service
  ETHERGOLD_ENV_FILE="${ETHERGOLD_ETC}/ethergold.env"
  ETHERGOLD_ROLE_FILE="${ETHERGOLD_ETC}/role.env"
  ETHERGOLD_EDGE_ENV="${ETHERGOLD_ETC}/edge.env"
  ETHERGOLD_DISABLE_FILE="${ETHERGOLD_VAR}/disabled"
fi

echo "--- stop bench bridge (keep listen stack for re-enable) ---"
for unit in \
  fixture-prod.service ethergold.service \
  fixture-collector.service ethergold-pogcc-com.service \
  wg-quick@wg0.service; do
  systemctl stop "${unit}" 2>/dev/null || true
  systemctl disable "${unit}" 2>/dev/null || true
done
systemctl stop ethergold-collector.service ethergold-http.service 2>/dev/null || true
pkill -TERM -f 'pog422_fixture_bridge|pog422_bridge|pog422_fixture_listen|ethergold_listen_supervisor|fixture_listen_supervisor|fixture_supervisor' 2>/dev/null || true
sleep 1
pkill -KILL -f 'pog422_fixture_bridge|pog422_bridge|pog422_fixture_listen|ethergold_listen_supervisor|fixture_listen_supervisor|fixture_supervisor' 2>/dev/null || true

echo "--- stamp listen stock (DF QR; collector+HTTP on boot; never inject) ---"
# listen_ohd: collector + DF TBX + HTTP. Never inject. atlas_copper / topbox withdrawn.
mkdir -p "${ETHERGOLD_ETC}" "${ETHERGOLD_VAR}"
{
  echo "ETHERGOLD_ROLE=listen"
} > "${ETHERGOLD_ROLE_FILE}"
{
  echo "FIXTURE_POS=1"
  echo "CHANNEL=both"
  echo "POG422_UARTD=1"
  echo "POG422_UARTD_INJECT=0"
  echo "FIXTURE_STATUS_LED=1"
  echo "FIELD_PROFILE=listen_ohd"
  echo "ETHERGOLD_CURRENT_GAME_IPC=write"
} > "${ETHERGOLD_ENV_FILE}"
echo "EDGE_MODE=0" > "${ETHERGOLD_EDGE_ENV}"
rm -f "${ETHERGOLD_DISABLE_FILE}"

echo "--- DyzineFrame first-boot (autostart ON, configset false) ---"
DF_DISABLE="${HOME_TB}/EtherGold/sync/disable_dyzineframe_autostart.sh"
if [[ -f "${DF_DISABLE}" ]]; then
  sudo -u "${REAL_USER}" bash "${DF_DISABLE}" --enable || true
fi
DF_INI="${HOME_TB}/DyzineFrame/config.ini"
if [[ -f "${DF_INI}" ]]; then
  python3 - "${DF_INI}" <<'PY'
import pathlib, re, sys
p = pathlib.Path(sys.argv[1])
text = p.read_text(encoding="utf-8", errors="replace")
subs = {
    r"(?im)^(configset\s*=\s*).*$": r"\g<1>False",
    r"(?im)^(asset_number\s*=\s*).*$": r"\g<1>0",
    r"(?im)^(pog_asset_number\s*=\s*).*$": r"\g<1>0",
    r"(?im)^(bank_number\s*=\s*).*$": r"\g<1>0",
}
for pat, repl in subs.items():
    text, n = re.subn(pat, repl, text, count=1)
    if n == 0:
        sys.stderr.write(f"WARN: no key matched {pat}\n")
p.write_text(text, encoding="utf-8")
print(f"updated {p}")
PY
else
  echo "WARN: no ${DF_INI}" >&2
fi

echo "--- seed latest DyzineFrame from Dropbox (no display restart) ---"
if [[ "${SKIP_DF_SEED:-0}" == "1" ]]; then
  echo "SKIP_DF_SEED=1 — leaving DyzineFrame files for a later LAN seed"
else
DF_SYNC="${HOME_TB}/DyzineFrame/sync"
if [[ -x "${DF_SYNC}/seed_from_dropbox.sh" ]] || [[ -f "${DF_SYNC}/seed_from_dropbox.sh" ]]; then
  sudo -u "${REAL_USER}" bash "${DF_SYNC}/seed_from_dropbox.sh" || {
    echo "WARN: seed_from_dropbox.sh failed — card may stay on old DyzineFrame" >&2
  }
elif [[ -f "${DF_SYNC}/stage_from_dropbox.sh" ]]; then
  sudo -u "${REAL_USER}" bash "${DF_SYNC}/stage_from_dropbox.sh" || true
  sudo -u "${REAL_USER}" env FORCE=1 PROMOTE_RESTART=0 bash "${DF_SYNC}/promote_staging.sh" || {
    echo "WARN: promote_staging.sh failed" >&2
  }
  sudo -u "${REAL_USER}" bash "${DF_SYNC}/install_pi_deploy_schedule.sh" || true
else
  echo "WARN: no ${DF_SYNC}/stage_from_dropbox.sh — DyzineFrame files not updated" >&2
fi
fi
loginctl enable-linger "${REAL_USER}" 2>/dev/null || true
EG_SYNC="${HOME_TB}/EtherGold/sync"
if [[ -f "${EG_SYNC}/install_pi_deploy_schedule.sh" ]]; then
  sudo -u "${REAL_USER}" bash "${EG_SYNC}/install_pi_deploy_schedule.sh" || {
    echo "WARN: EtherGold deploy timers not installed" >&2
  }
fi
if [[ -f "${EG_SYNC}/install_hs_out_idle.sh" ]]; then
  sudo -u "${REAL_USER}" bash "${EG_SYNC}/install_hs_out_idle.sh" || {
    echo "WARN: HS OUT idle not installed" >&2
  }
fi
# Re-enable after set_ethergold_role listen (that helper disables DF). Supervisor autostart.
sudo -u "${REAL_USER}" bash -lc 'mkdir -p ~/.config/autostart; if [[ -f ~/DyzineFrame/topboxboot.desktop ]]; then cp -f ~/DyzineFrame/topboxboot.desktop ~/.config/autostart/topboxboot.desktop; chmod +x ~/DyzineFrame/run_supervisor.sh 2>/dev/null || true; echo "autostart -> run_supervisor.sh"; fi' || true
if [[ -f "${HOME_TB}/DyzineFrame/VERSION.txt" ]]; then
  echo "DyzineFrame VERSION=$(cat "${HOME_TB}/DyzineFrame/VERSION.txt")"
fi

echo "--- wipe bench identity / capture ---"
rm -f "${HOME_TB}/EtherGold/fixture-bridge.env" \
  "${HOME_TB}/EtherGold/progressives.csv" \
  "${HOME_TB}/EtherGold/floor-games.json" \
  /etc/fixture/fixture-pos.env \
  /etc/fixture/fixture-bridge.env 2>/dev/null || true
if [[ -f "${HOME_TB}/EtherGold/sync/rclone.env" ]]; then
  sed -i 's|^DROPBOX_DEST=.*|# DROPBOX_DEST= (cleared listen-stock)|' \
    "${HOME_TB}/EtherGold/sync/rclone.env" || true
  sed -i 's|^FIXTURE_POS=.*|FIXTURE_POS=1|' \
    "${HOME_TB}/EtherGold/sync/rclone.env" || true
fi
mkdir -p "${HOME_TB}/EtherGold/logs"
find "${HOME_TB}/EtherGold/logs" -maxdepth 2 -type f \( -name '*.jsonl' -o -name '*.log' -o -name 'progressives.csv' -o -name 'floor-games.json' \) -delete 2>/dev/null || true
hostnamectl set-hostname topbox || true
echo topbox > /etc/hostname
# Stock hostname stays topbox (asset unknown). Field Apply may later stamp
# topbox_<asset> when ETHERGOLD_STAMP_HOSTNAME=1. Linux user remains topbox.

echo "--- remove workshop ~/EtherGold/dev (not Linux /dev) ---"
# Listen stock keeps prod + sync. Run this script from /tmp so the tree can go.
DEV_TREE="${HOME_TB}/EtherGold/dev"
if [[ -d "${DEV_TREE}" ]]; then
  case "${SCRIPT_DIR}/" in
    "${DEV_TREE}"/*)
      echo "FATAL: script is inside ${DEV_TREE} — copy to /tmp and re-run" >&2
      exit 1
      ;;
  esac
  rm -rf "${DEV_TREE}"
  echo "removed ${DEV_TREE}"
else
  echo "OK: no ${DEV_TREE}"
fi
mkdir -p "${HOME_TB}/EtherGold/prod" "${ETHERGOLD_ETC}"
cp -f "${BASH_SOURCE[0]}" "${HOME_TB}/EtherGold/prod/prepare_listen_stock.sh"
chmod 0755 "${HOME_TB}/EtherGold/prod/prepare_listen_stock.sh"
# Production pins prod; never fall back to workshop ~/EtherGold/dev.
{
  echo "ETHERGOLD_ROOT=${HOME_TB}/EtherGold"
  echo "ETHERGOLD_PROD=${HOME_TB}/EtherGold/prod"
  echo "ETHERGOLD_SYNC=${HOME_TB}/EtherGold/sync"
  echo "ETHERGOLD_LOGS=${HOME_TB}/EtherGold/logs"
  echo "ETHERGOLD_RUNTIME=${HOME_TB}/EtherGold/prod"
  echo "ETHERGOLD_BRIDGE=${HOME_TB}/EtherGold/prod"
  echo "ETHERGOLD_DAEMON=${HOME_TB}/EtherGold/prod"
} > "${ETHERGOLD_ETC}/runtime.env"
chmod 644 "${ETHERGOLD_ETC}/runtime.env" "${ETHERGOLD_ETC}/LISTEN_STOCK" "${ETHERGOLD_ENV_FILE}" "${ETHERGOLD_ROLE_FILE}" 2>/dev/null || true
touch "${ETHERGOLD_ETC}/LISTEN_STOCK"
chmod 644 "${ETHERGOLD_ETC}/LISTEN_STOCK"

echo "--- enable POG422 listen + HTTP on boot ---"
rm -f "${ETHERGOLD_DISABLE_FILE}"
if [[ -f "${SCRIPT_DIR}/install_collector_service.sh" ]]; then
  CHANNEL=both FIXTURE_POS=1 bash "${SCRIPT_DIR}/install_collector_service.sh"
else
  echo "WARN: missing ${SCRIPT_DIR}/install_collector_service.sh" >&2
fi
# install_collector merges env; re-stamp inject=0 in case an older copy ran.
{
  echo "FIXTURE_POS=1"
  echo "CHANNEL=both"
  echo "POG422_UARTD=1"
  echo "POG422_UARTD_INJECT=0"
  echo "FIXTURE_STATUS_LED=1"
  echo "FIELD_PROFILE=listen_ohd"
  echo "ETHERGOLD_CURRENT_GAME_IPC=write"
} > "${ETHERGOLD_ENV_FILE}"
if [[ -f "${SCRIPT_DIR}/install_ethergold_http.sh" ]]; then
  bash "${SCRIPT_DIR}/install_ethergold_http.sh" || {
    echo "WARN: ethergold-http install failed (often :31234 still held by DyzineFrame)" >&2
  }
else
  echo "WARN: missing ${SCRIPT_DIR}/install_ethergold_http.sh" >&2
fi
systemctl restart "${ETHERGOLD_COLLECTOR_UNIT}" 2>/dev/null || true
rm -f "${HOME_TB}/EtherGold/sync/"_tmp_* 2>/dev/null || true
if [[ -f "${HOME_TB}/EtherGold/sync/ethergold_paths.sh" ]]; then
  # Force sourced runtime.env even on older pulled copies until Dropbox catches up.
  if ! grep -q '/etc/ethergold/runtime.env' "${HOME_TB}/EtherGold/sync/ethergold_paths.sh"; then
    sed -i '1a source /etc/ethergold/runtime.env 2>/dev/null || true' \
      "${HOME_TB}/EtherGold/sync/ethergold_paths.sh"
  fi
fi

echo "--- wlan1 idle (keep driver) ---"
if command -v nmcli >/dev/null 2>&1; then
  while IFS=: read -r uuid name device state type; do
    [[ -z "${uuid}" ]] && continue
    if [[ "${device}" == "wlan1" ]]; then
      nmcli connection delete "${uuid}" 2>/dev/null || true
      continue
    fi
    # --keep-office-wifi: never drop the live SSH link (office LAN or POGCOM).
    if [[ "${STRIP_WIFI}" != "1" ]]; then
      if [[ "${state}" == "activated" ]]; then
        continue
      fi
      if [[ "${name}" == *POGCOM* ]]; then
        continue
      fi
      if [[ "${type}" == "802-11-wireless" ]]; then
        nmcli connection delete "${uuid}" 2>/dev/null || true
      fi
    fi
  done < <(nmcli -t -f UUID,NAME,DEVICE,STATE,TYPE connection show)
  if [[ "${STRIP_WIFI}" == "1" ]]; then
    echo "--- strip all NM Wi-Fi (wlan0 admin will drop) ---"
    while IFS=: read -r uuid name type; do
      [[ "${type}" == "802-11-wireless" ]] || continue
      nmcli connection delete "${uuid}" 2>/dev/null || true
    done < <(nmcli -t -f UUID,NAME,TYPE connection show)
  fi
fi

echo "=== verify ---"
echo "hostname=$(hostname)"
echo "role=$(cat "${ETHERGOLD_ROLE_FILE}" 2>/dev/null || echo missing)"
echo "inject=$(grep POG422_UARTD_INJECT "${ETHERGOLD_ENV_FILE}" 2>/dev/null || echo missing)"
echo "disable_file=$( [[ -f "${ETHERGOLD_DISABLE_FILE}" ]] && echo present-ERROR || echo absent )"
echo "wlan0=$(ip -4 -br addr show wlan0 2>/dev/null || true)"
echo "wlan1=$(ip -4 -br addr show wlan1 2>/dev/null || echo none)"
systemctl is-enabled fixture-prod.service 2>/dev/null || echo "fixture-prod not-enabled"
systemctl is-enabled ethergold.service 2>/dev/null || echo "ethergold-bridge not-enabled"
systemctl is-enabled ethergold-collector.service 2>/dev/null || echo "collector not-enabled"
systemctl is-active ethergold-collector.service 2>/dev/null || echo "collector inactive"
if [[ -f "${DF_INI}" ]]; then
  grep -E '^(configset|asset_number|bank_number)' "${DF_INI}" || true
fi
if [[ -f "${HOME_TB}/DyzineFrame/VERSION.txt" ]]; then
  echo "df_version=$(cat "${HOME_TB}/DyzineFrame/VERSION.txt")"
fi
test ! -f "${HOME_TB}/EtherGold/progressives.csv"
test ! -f "${HOME_TB}/EtherGold/floor-games.json"
test ! -d "${HOME_TB}/EtherGold/dev"
echo "runtime=$(grep ETHERGOLD_RUNTIME /etc/ethergold/runtime.env 2>/dev/null || echo missing)"
echo "=== prepare_listen_stock done mac=${MAC0} ==="
