#!/bin/bash
# Установка Patriot Bridge на Orange Pi Zero 3 / Raspberry Pi / Wiren Board 6-7 (Debian 11+, Python ≥ 3.9).
# Запуск на самой коробке (с интернетом):
#   curl -fsSL https://patriot-systems.ru/bridge/install-bridge.sh | sudo bash -s -- --email you@mail.ru --password '...' [--port /dev/ttyS5] [--baud 115200] [--video]
#   Orange Pi Zero 3 (корпус Patriot Bridge v2): сам включает UART5 (RS-485, пины 8/10) и SPI1 (подсветка), тампер,
#   и перезагружает плату (--no-reboot — не перезагружать). Порт: USB-переходник RS-485, если вставлен, иначе UART5.
#   Настройки Modbus ПП знать не нужно: агент сам подбирает скорость, чётность и адрес ПП (автопоиск).
#   --video — видеонаблюдение: go2rtc (arm64/armv7, проверка sha256), ffmpeg (снапшоты), websockets (туннель просмотра).
# Что делает: ставит python-venv и агент, регистрирует коробку в вашем кабинете PRO (получает код привязки),
# пишет /etc/orion-agent/agent.yaml, включает службу. Код привязки печатается в конце — наклейте его на корпус.
set -euo pipefail

SERVER="https://patriot-systems.ru/pro"
VIDEO=0; GO2RTC_VER="1.9.14"; REBOOT=1
PORT=""; BAUD=115200; EMAIL=""; PASSWORD=""; CODE=""; PKG_URL="https://patriot-systems.ru/bridge/orion-agent.tar.gz"
while [ $# -gt 0 ]; do
  case "$1" in
    --server) SERVER="$2"; shift 2;;
    --port) PORT="$2"; shift 2;;
    --baud) BAUD="$2"; shift 2;;
    --email) EMAIL="$2"; shift 2;;
    --password) PASSWORD="$2"; shift 2;;
    --code) CODE="$2"; shift 2;;          # если коробка уже зарегистрирована в PRO — просто задать код
    --pkg) PKG_URL="$2"; shift 2;;
    --video) VIDEO=1; shift;;
    --no-reboot) REBOOT=0; shift;;
    *) echo "неизвестный параметр $1"; exit 1;;
  esac
done
[ "$(id -u)" = 0 ] || { echo "запускать от root (sudo)"; exit 1; }

echo "== 1/5 пакеты"
PYV="$(python3 -c 'import sys;print(sys.version_info[0]*100+sys.version_info[1])' 2>/dev/null || echo 0)"
[ "$PYV" -ge 309 ] || { echo "нужен Python >= 3.9 (на коробке $(python3 --version 2>&1)). Wiren Board: обновите ПО контроллера до релиза на Debian 11 (bullseye) в веб-интерфейсе → Настройки → Обновление ПО."; exit 1; }
apt-get update -qq && apt-get install -y -qq python3 python3-venv python3-pip curl >/dev/null

echo "== 2/5 агент"
mkdir -p /opt/orion-agent /etc/orion-agent /var/lib/orion-agent
cd /opt/orion-agent
if [ -d /tmp/orion-agent-src ]; then SRC=/tmp/orion-agent-src; else
  curl -fsSL "$PKG_URL" -o /tmp/orion-agent.tar.gz && rm -rf /tmp/orion-agent-src && mkdir -p /tmp/orion-agent-src && tar xzf /tmp/orion-agent.tar.gz -C /tmp/orion-agent-src --strip-components=1
  SRC=/tmp/orion-agent-src
fi
[ -d .venv ] || python3 -m venv .venv
./.venv/bin/pip install -q --upgrade pip >/dev/null
MODEL="$(tr -d '\0' < /proc/device-tree/model 2>/dev/null || true)"
BOARD=""; NEED_REBOOT=0
case "$MODEL" in *[Zz]ero3*|*[Zz]ero\ 3*) BOARD=opi-zero3;; esac
if [ "$BOARD" = opi-zero3 ]; then
  echo "   плата: $MODEL — ставлю поддержку подсветки и тампера"
  apt-get install -y -qq gcc python3-dev >/dev/null || true
  ./.venv/bin/pip install -q "$SRC[bridge]" >/dev/null || { echo "   ! spidev/gpiod не встали — подсветка будет выключена"; ./.venv/bin/pip install -q "$SRC" >/dev/null; }
else
  ./.venv/bin/pip install -q "$SRC" >/dev/null
fi

if [ "$VIDEO" = 1 ]; then
  echo "== видео: go2rtc $GO2RTC_VER + ffmpeg"
  ARCH="$(dpkg --print-architecture 2>/dev/null || uname -m)"
  case "$ARCH" in
    arm64|aarch64) GA=arm64; GSUM=359fabade8a7a51e81a55fe6df6b0ef81764a5e1d63179577534eaaa71904b50;;
    armhf|armv7l|arm) GA=arm; GSUM=4d7e1639af5a2722a28e864468fd8099b3c1682565446c798bf9e3b38fde12e4;;
    amd64|x86_64) GA=amd64; GSUM=32d616af226bd731678ffde328b94cfb94e30339bfefc469cfb76323144615a6;;
    *) echo "архитектура $ARCH не поддерживается сборками go2rtc"; exit 1;;
  esac
  mkdir -p /opt/orion-agent/bin /var/lib/orion-agent/video
  # сначала зеркало Patriot (GitHub из РФ бывает недоступен), затем GitHub; контрольная сумма обязательна
  MIRROR="${PKG_URL%/*}/go2rtc_${GO2RTC_VER}_linux_${GA}"
  rm -f /tmp/go2rtc.dl
  curl -fsSL "$MIRROR" -o /tmp/go2rtc.dl || curl -fsSL "https://github.com/AlexxIT/go2rtc/releases/download/v${GO2RTC_VER}/go2rtc_linux_${GA}" -o /tmp/go2rtc.dl
  echo "$GSUM  /tmp/go2rtc.dl" | sha256sum -c --quiet - || { echo "go2rtc: контрольная сумма не совпала"; exit 1; }
  install -m 755 /tmp/go2rtc.dl /opt/orion-agent/bin/go2rtc && rm -f /tmp/go2rtc.dl
  apt-get install -y -qq --no-install-recommends ffmpeg >/dev/null || echo "   ! ffmpeg не установился — снапшоты RTSP-камер будут недоступны"
  ./.venv/bin/pip install -q "websockets>=10" >/dev/null
  echo "   $(/opt/orion-agent/bin/go2rtc -version 2>&1 | head -1)"
fi

echo "== 3/5 порт RS-485"
SPI_DEV=0
if [ "$BOARD" = opi-zero3 ]; then
  # UART5 (PH2/PH3, пины 8/10) и SPI1 (PH7, пин 19) включаются оверлеями; действуют после перезагрузки
  add_ov() { # файл ключ значение…
    local f="$1" k="$2"; shift 2
    local cur; cur="$(grep -E "^$k=" "$f" | head -1 | cut -d= -f2- || true)"
    local new="$cur"; for o in "$@"; do case " $new " in *" $o "*) ;; *) new="${new:+$new }$o";; esac; done
    if [ "$new" != "$cur" ]; then
      if grep -qE "^$k=" "$f"; then sed -i "s|^$k=.*|$k=$new|" "$f"; else echo "$k=$new" >> "$f"; fi
      NEED_REBOOT=1
    fi
  }
  if [ -f /boot/orangepiEnv.txt ]; then
    add_ov /boot/orangepiEnv.txt overlays ph-uart5 spi1-cs1-spidev; SPI_DEV=1
  elif [ -f /boot/armbianEnv.txt ]; then
    grep -q '^overlay_prefix=' /boot/armbianEnv.txt || { echo "overlay_prefix=sun50i-h616" >> /boot/armbianEnv.txt; NEED_REBOOT=1; }
    add_ov /boot/armbianEnv.txt overlays uart5 spidev1_0
    grep -q '^param_spidev_spi_bus=' /boot/armbianEnv.txt || { echo "param_spidev_spi_bus=1" >> /boot/armbianEnv.txt; NEED_REBOOT=1; }
  else
    echo "   ! не нашёл /boot/orangepiEnv.txt или /boot/armbianEnv.txt — включите UART5 и SPI1 вручную (PINOUT.md)"
  fi
  [ "$NEED_REBOOT" = 1 ] && echo "   UART5 и SPI1 включены (заработают после перезагрузки)"
fi
if [ -z "$PORT" ]; then
  # USB-переходник — для стенда; в корпусе Bridge его нет, и порт — UART5
  for p in /dev/ttyRS485-1 /dev/ttyUSB0 /dev/ttyS5 /dev/ttyAS5 /dev/ttyAML0 /dev/ttyAMA0 /dev/serial0; do [ -e "$p" ] && { PORT="$p"; break; }; done
  [ -z "$PORT" ] && [ "$BOARD" = opi-zero3 ] && PORT=/dev/ttyS5
fi
[ -n "$PORT" ] || { echo "не нашёл последовательный порт, укажите --port"; exit 1; }
echo "   порт: $PORT @ $BAUD"

DEVICE_ID="$(cut -c1-16 /etc/machine-id)"
echo "== 4/5 регистрация коробки в кабинете PRO (device_id $DEVICE_ID)"
if [ -z "$CODE" ]; then
  [ -n "$EMAIL" ] || { echo "нужен --email/--password инсталлятора или --code"; exit 1; }
  TOKEN="$(curl -fsS -X POST "$SERVER/api/auth/login" -H 'Content-Type: application/json' -d "{\"email\":\"$EMAIL\",\"password\":\"$PASSWORD\"}" | python3 -c 'import sys,json;print(json.load(sys.stdin)["token"])')"
  RESP="$(curl -sS -X POST "$SERVER/api/bridges" -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d "{\"device_id\":\"$DEVICE_ID\"}")"
  CODE="$(echo "$RESP" | python3 -c 'import sys,json;d=json.load(sys.stdin);print(d.get("claim_code",""))' || true)"
  if [ -z "$CODE" ]; then
    # уже зарегистрирована — берём из списка
    CODE="$(curl -fsS "$SERVER/api/bridges" -H "Authorization: Bearer $TOKEN" | python3 -c "import sys,json;print(next(b['claim_code'] for b in json.load(sys.stdin) if b['device_id']=='$DEVICE_ID'))")"
  fi
fi

cat > /etc/orion-agent/agent.yaml <<EOF
# Patriot Bridge — сгенерировано install-bridge.sh $(date +%F)
provision:
  server_url: $SERVER
  claim_code: $CODE
link:
  type: serial
  port: $PORT
  baudrate: $BAUD
  parity: N
  stopbits: 1
pp:
  - unit: 1
poll:
  event_interval: 0.25
  full_sync_interval: 60
  analog_interval: 30
  watchdog_interval: 20
store_path: /var/lib/orion-agent/agent.db
log_level: INFO
EOF
if [ "$BOARD" = opi-zero3 ]; then cat >> /etc/orion-agent/agent.yaml <<EOF
led:                         # логотип-индикатор и тампер корпуса Patriot Bridge v2
  enabled: true
  spi_bus: 1
  spi_dev: $SPI_DEV
  count: 7
  order: GRB
  tamper_gpio: 70            # PC6, пин 11
EOF
fi
if [ "$VIDEO" = 1 ]; then cat >> /etc/orion-agent/agent.yaml <<EOF
video:
  enabled: true
  go2rtc_bin: /opt/orion-agent/bin/go2rtc
  work_dir: /var/lib/orion-agent/video
  webrtc_port: 8555          # UDP/TCP для P2P; проброс портов на роутере не нужен
EOF
fi

echo "== 5/5 служба"
cat > /etc/systemd/system/orion-agent.service <<'EOF'
[Unit]
Description=Patriot Bridge agent (С2000-ПП ↔ Patriot Cloud)
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
ExecStart=/opt/orion-agent/.venv/bin/orion-agent run -c /etc/orion-agent/agent.yaml
Restart=always
RestartSec=5
User=root

[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload; systemctl enable --now orion-agent >/dev/null
sleep 2; systemctl is-active orion-agent >/dev/null && echo "   служба запущена"

cat <<EOF

====================================================
  PATRIOT BRIDGE готов.
  device id : $DEVICE_ID
  КОД ПРИВЯЗКИ (на наклейку) :  $CODE
====================================================
Дальше: в кабинете PRO → объект → «Ввод в эксплуатацию» → ввести код → коробка подключится сама.
Логи: journalctl -u orion-agent -f
EOF
if [ "$NEED_REBOOT" = 1 ]; then
  if [ "$REBOOT" = 1 ]; then echo "Перезагрузка через 10 с, чтобы включились UART5 и подсветка…"; sleep 10; reboot
  else echo "ВНИМАНИЕ: перезагрузите плату (reboot), иначе порт UART5 и подсветка не заработают."; fi
fi
