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

PRODUCT='Gorsee MCP'
CONTROL_BASE='https://install.178.212.14.102.sslip.io'
CLUB_URL='https://club.gorseecode.ru'
INSTALL_ROOT='/opt/gorsee-mcp'
CONFIG_ROOT='/etc/gorsee-mcp'
STATE_ROOT='/var/lib/gorsee-mcp'
LOG_ROOT='/var/log/gorsee-mcp'
LOG_FILE="$LOG_ROOT/install.log"

exec 3>&1
mkdir -p "$LOG_ROOT"
chmod 700 "$LOG_ROOT"
exec 1>>"$LOG_FILE" 2>&1

say(){ printf '%s\n' "$*" >&3; }
fail(){ say "Ошибка: $*"; say "Подробности: $LOG_FILE"; exit 1; }
need_root(){ [[ ${EUID:-$(id -u)} -eq 0 ]] || fail "запустите установку через sudo"; }
json_get(){ python3 -c 'import json,sys; d=json.load(sys.stdin); print(d.get(sys.argv[1], ""))' "$1"; }
post_json(){ curl -fsS --connect-timeout 15 --max-time 45 -H 'content-type: application/json' -d "$2" "$CONTROL_BASE$1"; }

need_root
say "$PRODUCT"
say "Проверяю сервер..."
command -v curl >/dev/null || { apt-get update -qq && apt-get install -y -qq curl; }
command -v python3 >/dev/null || { apt-get update -qq && apt-get install -y -qq python3; }
command -v openssl >/dev/null || { apt-get update -qq && apt-get install -y -qq openssl; }

read -r -p 'Введите свою почту, Telegram username или Telegram user ID: ' IDENTITY </dev/tty
IDENTITY="$(printf '%s' "$IDENTITY" | tr '[:upper:]' '[:lower:]' | xargs | sed 's/^@//')"
[[ -n "$IDENTITY" ]] || fail 'значение не введено'

FINGERPRINT_SOURCE="$(cat /etc/machine-id 2>/dev/null || hostname)"
FINGERPRINT="$(printf '%s' "$FINGERPRINT_SOURCE" | sha256sum | awk '{print $1}')"
HOSTNAME_VALUE="$(hostname 2>/dev/null || echo server)"
CLAIM_BODY="$(python3 - <<PY
import json
print(json.dumps({'identity': '$IDENTITY', 'fingerprint': '$FINGERPRINT', 'hostname': '$HOSTNAME_VALUE'}))
PY
)"
set +e
CLAIM="$(curl -sS --connect-timeout 15 --max-time 45 -w '\n%{http_code}' -H 'content-type: application/json' -d "$CLAIM_BODY" "$CONTROL_BASE/v1/claim")"
RC=$?
set -e
[[ $RC -eq 0 ]] || fail 'не удалось связаться с сервисом установки'
HTTP="${CLAIM##*$'\n'}"; BODY="${CLAIM%$'\n'*}"
if [[ "$HTTP" == '403' ]]; then
  say 'У вас нет доступа к Gorsee MCP.'
  say "Оформить подписку: $CLUB_URL"
  exit 1
fi
if [[ "$HTTP" == '409' ]]; then
  say 'Для этого участника уже активирован Gorsee MCP на другом сервере.'
  say 'Если старый сервер больше не существует, повторите установку после того, как он будет признан недоступным.'
  exit 1
fi
[[ "$HTTP" == '200' ]] || fail "сервис установки ответил HTTP $HTTP"

INSTALL_ID="$(printf '%s' "$BODY" | json_get installation_id)"
CLAIM_TOKEN="$(printf '%s' "$BODY" | json_get claim_token)"
RELEASE_SHA="$(printf '%s' "$BODY" | json_get release_sha256)"
[[ -n "$INSTALL_ID" && -n "$CLAIM_TOKEN" && -n "$RELEASE_SHA" ]] || fail 'неполный ответ сервиса установки'

say 'Доступ подтверждён.'
say 'Устанавливаю Gorsee MCP...'
TMP="$(mktemp -d)"; trap 'rm -rf "$TMP"' EXIT
curl -fsS --retry 3 --connect-timeout 15 --max-time 300 "$CONTROL_BASE/v1/release?installation_id=$INSTALL_ID&claim_token=$CLAIM_TOKEN" -o "$TMP/gorsee-mcp.tgz"
printf '%s  %s\n' "$RELEASE_SHA" "$TMP/gorsee-mcp.tgz" | sha256sum -c - >/dev/null || fail 'проверка целостности релиза не пройдена'

apt-get update -qq
DEBIAN_FRONTEND=noninteractive apt-get install -y -qq ca-certificates curl tar caddy
if ! command -v node >/dev/null || [[ "$(node -p 'Number(process.versions.node.split(`.`)[0])' 2>/dev/null || echo 0)" -lt 20 ]]; then
  curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
  DEBIAN_FRONTEND=noninteractive apt-get install -y -qq nodejs
fi

mkdir -p "$INSTALL_ROOT" "$CONFIG_ROOT" "$STATE_ROOT"
chmod 700 "$CONFIG_ROOT" "$STATE_ROOT"
rm -rf "$INSTALL_ROOT"/*
tar -xzf "$TMP/gorsee-mcp.tgz" -C "$INSTALL_ROOT"
cd "$INSTALL_ROOT"
[[ -f package.json ]] || fail 'релиз Gorsee MCP повреждён'
npm install --omit=dev --no-audit --no-fund >/dev/null

PUBLIC_IP="$(curl -4fsS --max-time 10 https://api.ipify.org || true)"
[[ "$PUBLIC_IP" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]] || fail 'не удалось определить публичный IPv4 сервера'
PUBLIC_HOST="mcp.${PUBLIC_IP}.sslip.io"
PUBLIC_URL="https://${PUBLIC_HOST}"
HUB_TOKEN="$(openssl rand -hex 32)"
VAULT_KEY="$(openssl rand -hex 32)"
printf '%s' "$HUB_TOKEN" > "$CONFIG_ROOT/hub-token"
printf '%s' "$VAULT_KEY" > "$CONFIG_ROOT/vault-key"
chmod 600 "$CONFIG_ROOT/hub-token" "$CONFIG_ROOT/vault-key"

cat > "$CONFIG_ROOT/env" <<EOF
NODE_ENV=production
GORSEE_HOST=127.0.0.1
GORSEE_PORT=8787
GORSEE_PUBLIC_URL=$PUBLIC_URL
GORSEE_HUB_TOKEN_FILE=$CONFIG_ROOT/hub-token
GORSEE_SECRET_VAULT_KEY_FILE=$CONFIG_ROOT/vault-key
GORSEE_DATA_DIR=$STATE_ROOT
EOF
chmod 600 "$CONFIG_ROOT/env"

START_FILE='dist/hub.js'
[[ -f "$INSTALL_ROOT/$START_FILE" ]] || START_FILE='src/hub.ts'
cat > /etc/systemd/system/gorsee-mcp-hub.service <<EOF
[Unit]
Description=Gorsee MCP Hub
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
WorkingDirectory=$INSTALL_ROOT
EnvironmentFile=$CONFIG_ROOT/env
ExecStart=/usr/bin/node $INSTALL_ROOT/$START_FILE
Restart=always
RestartSec=3
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ReadWritePaths=$STATE_ROOT $INSTALL_ROOT
[Install]
WantedBy=multi-user.target
EOF

cat > /etc/caddy/Caddyfile <<EOF
$PUBLIC_HOST {
  encode zstd gzip
  reverse_proxy 127.0.0.1:8787
}
EOF
systemctl daemon-reload
systemctl enable --now caddy gorsee-mcp-hub

for _ in $(seq 1 40); do curl -fsS http://127.0.0.1:8787/healthz >/dev/null 2>&1 && break; sleep 2; done
curl -fsS http://127.0.0.1:8787/healthz >/dev/null || fail 'Gorsee MCP Hub не запустился'
for _ in $(seq 1 45); do curl -fsS --connect-timeout 4 --max-time 8 "$PUBLIC_URL/healthz" >/dev/null 2>&1 && break; sleep 2; done
curl -fsS --connect-timeout 5 --max-time 10 "$PUBLIC_URL/healthz" >/dev/null || fail 'публичный HTTPS адрес не стал доступен. Проверьте, что порты 80 и 443 открыты у хостера.'

FINISH_BODY="$(python3 - <<PY
import json
print(json.dumps({'installation_id':'$INSTALL_ID','claim_token':'$CLAIM_TOKEN','public_url':'$PUBLIC_URL'}))
PY
)"
FINISH="$(post_json /v1/finish "$FINISH_BODY")"
INSTALL_SECRET="$(printf '%s' "$FINISH" | json_get installation_secret)"
[[ -n "$INSTALL_SECRET" ]] || fail 'не удалось активировать установку'
printf '%s' "$INSTALL_ID" > "$CONFIG_ROOT/installation-id"
printf '%s' "$INSTALL_SECRET" > "$CONFIG_ROOT/installation-secret"
chmod 600 "$CONFIG_ROOT/installation-id" "$CONFIG_ROOT/installation-secret"

cat > /usr/local/bin/gorsee <<'EOS'
#!/usr/bin/env bash
set -euo pipefail
CONFIG=/etc/gorsee-mcp
PUBLIC_URL=$(grep '^GORSEE_PUBLIC_URL=' "$CONFIG/env" | cut -d= -f2-)
TOKEN=$(cat "$CONFIG/hub-token")
case "${1:-}" in
  mcp|'')
    echo 'Gorsee MCP'
    echo
    echo "ChatGPT: ${PUBLIC_URL}/mcp?gorsee_token=${TOKEN}"
    echo
    echo 'Подключение дополнительного устройства:'
    curl -fsS -X POST -H "Authorization: Bearer ${TOKEN}" "${PUBLIC_URL}/product/device-enroll" 2>/dev/null || echo 'Не удалось создать одноразовую ссылку подключения.'
    echo
    ;;
  status) systemctl --no-pager --full status gorsee-mcp-hub.service ;;
  *) echo 'Команды: gorsee mcp | gorsee status' ;;
esac
EOS
chmod 755 /usr/local/bin/gorsee
cat > /usr/local/bin/Gorsee <<'EOS'
#!/usr/bin/env bash
if [[ "${1:-}" == 'MCP' || "${1:-}" == 'mcp' || -z "${1:-}" ]]; then exec /usr/local/bin/gorsee mcp; fi
exec /usr/local/bin/gorsee "$@"
EOS
chmod 755 /usr/local/bin/Gorsee

cat > /etc/systemd/system/gorsee-mcp-heartbeat.service <<EOF
[Unit]
Description=Gorsee MCP license heartbeat
[Service]
Type=oneshot
ExecStart=/bin/bash -lc 'curl -fsS -H "content-type: application/json" -d "{\"installation_id\":\"\$(cat $CONFIG_ROOT/installation-id)\",\"installation_secret\":\"\$(cat $CONFIG_ROOT/installation-secret)\"}" "$CONTROL_BASE/v1/heartbeat" >/dev/null'
EOF
cat > /etc/systemd/system/gorsee-mcp-heartbeat.timer <<EOF
[Unit]
Description=Gorsee MCP heartbeat timer
[Timer]
OnBootSec=2min
OnUnitActiveSec=5min
RandomizedDelaySec=30
Persistent=true
[Install]
WantedBy=timers.target
EOF
systemctl daemon-reload
systemctl enable --now gorsee-mcp-heartbeat.timer

say ''
say 'Gorsee MCP установлен.'
say ''
say "Ссылка для ChatGPT:"
say "${PUBLIC_URL}/mcp?gorsee_token=${HUB_TOKEN}"
say ''
say 'Эти данные можно снова показать командой: Gorsee MCP'
say ''
/usr/local/bin/gorsee mcp >&3 || true
