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

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

failures=0

ok() {
  printf '[OK] %s\n' "$1"
}

warn() {
  printf '[WARN] %s\n' "$1"
}

fail() {
  printf '[FAIL] %s\n' "$1"
  failures=$((failures + 1))
}

require_file() {
  local path="$1"
  [[ -f "$path" ]] && ok "found $path" || fail "missing $path"
}

require_command() {
  local name="$1"
  command -v "$name" >/dev/null 2>&1 && ok "command available: $name" || fail "missing command: $name"
}

check_env_value() {
  local name="$1"
  local value="${!name:-}"
  if [[ -z "$value" ]]; then
    fail "missing .env value: $name"
    return
  fi
  case "$value" in
    change-*|pool.example.com|admin@example.com)
      fail "$name still has placeholder value"
      ;;
    *)
      ok "$name is set"
      ;;
  esac
}

check_port_number() {
  local name="$1"
  local value="${!name:-}"
  if [[ "$value" =~ ^[0-9]+$ ]] && (( value > 0 && value < 65536 )); then
    ok "$name port is valid: $value"
  else
    fail "$name is not a valid TCP port: ${value:-<empty>}"
  fi
}

check_port_conflict() {
  local name="$1"
  local value="${!name:-}"
  [[ -n "$value" ]] || return
  if command -v ss >/dev/null 2>&1 && ss -lnt | awk '{print $4}' | grep -Eq "[:.]${value}$"; then
    if [[ "$name" == "STRATUM_PORT" ]]; then
      fail "$name=$value is already listening. On a shared server, keep the existing pool on its original port and set Vexon to 4499."
    else
      warn "$name=$value is already listening; this may be expected if Vexon is already running"
    fi
  else
    ok "$name port is free: $value"
  fi
}

check_repo_ref() {
  local label="$1"
  local repo="$2"
  local ref="$3"

  if git ls-remote --exit-code --heads --tags "$repo" "$ref" >/dev/null 2>&1; then
    ok "$label repo/ref reachable: $ref"
  elif git ls-remote --exit-code "$repo" "refs/heads/$ref" >/dev/null 2>&1; then
    ok "$label branch reachable: $ref"
  elif git ls-remote --exit-code "$repo" "refs/tags/$ref" >/dev/null 2>&1; then
    ok "$label tag reachable: $ref"
  else
    fail "$label repo/ref not reachable: $repo $ref"
  fi
}

require_file .env
require_file install.sh
require_file templates/vexond.conf.tmpl
require_file templates/vexond-peer.conf.tmpl
require_file templates/vexonwallet.conf.tmpl
require_file templates/vexon-stratum.conf.tmpl
require_file templates/nginx-vexon-docs.conf.tmpl
require_file files/docs-site/index.html
require_file files/docs-site/assets/docs.css
require_file files/docs-site/assets/docs.js
require_file files/docs-site/assets/vexon-logo.png
require_file scripts/audit-vexon-clean.sh
require_file scripts/repair-miner-address.sh
require_file scripts/probe-miner-submit.sh

require_command bash
require_command git
require_command rsync
require_command sed
require_command awk

if command -v gh >/dev/null 2>&1; then
  if gh auth status >/dev/null 2>&1; then
    ok "GitHub CLI is authenticated"
  else
    warn "GitHub CLI is installed but not authenticated; private GitHub clones may fail"
  fi
else
  warn "GitHub CLI not installed; private GitHub clones require another HTTPS credential method"
fi

if [[ -f .env ]]; then
  set -a
  # shellcheck source=/dev/null
  if ! source .env; then
    fail ".env contains invalid shell syntax. Quote values with spaces, for example POOL_SITE_NAME=\"Vexon Pool\"."
  fi
  set +a

  POOL_DB_NAME="${POOL_DB_NAME:-vexonpool}"
  POOL_DB_USER="${POOL_DB_USER:-vexonpool}"
  STRATUM_DB_USER="${STRATUM_DB_USER:-vexonstratum}"
  STRATUM_PORT="${STRATUM_PORT:-4499}"
  VEX_BLOCK_SUBMIT_DIFF="${VEX_BLOCK_SUBMIT_DIFF:-503382015}"
  VEX_P2P_PORT="${VEX_P2P_PORT:-18555}"
  VEX_RPC_PORT="${VEX_RPC_PORT:-18556}"
  VEX_WALLET_RPC_PORT="${VEX_WALLET_RPC_PORT:-18557}"
  VEX_START_WALLET="${VEX_START_WALLET:-0}"
  VEX_WALLET_PASSPHRASE="${VEX_WALLET_PASSPHRASE:-}"
  VEX_CORE_REPO="${VEX_CORE_REPO:-https://github.com/vexonexchange-sudo/vexon-core.git}"
  VEX_WALLET_REPO="${VEX_WALLET_REPO:-https://github.com/vexonexchange-sudo/vexon-wallet.git}"
  VEX_STRATUM_REPO="${VEX_STRATUM_REPO:-https://github.com/vexonexchange-sudo/vexon-stratum.git}"
  VEX_CORE_REF="${VEX_CORE_REF:-main}"
  VEX_WALLET_REF="${VEX_WALLET_REF:-main}"
  VEX_STRATUM_REF="${VEX_STRATUM_REF:-main}"
  VEX_DOCS_DOMAIN="${VEX_DOCS_DOMAIN:-docs.vexonus.com}"
  VEX_MIN_PAYOUT="${VEX_MIN_PAYOUT:-0.001}"
  VEX_EARNINGS_CLEAR_DELAY="${VEX_EARNINGS_CLEAR_DELAY:-0}"
  VEX_MATURE_BLOCKS="${VEX_MATURE_BLOCKS:-100}"
  VEX_TXFEE="${VEX_TXFEE:-0}"
  VEX_BACKEND_CAN_STOP_NGINX="${VEX_BACKEND_CAN_STOP_NGINX:-0}"
  VEX_ENABLE_LOCAL_PEER="${VEX_ENABLE_LOCAL_PEER:-1}"
  VEX_PEER_P2P_PORT="${VEX_PEER_P2P_PORT:-18565}"
  VEX_PEER_RPC_PORT="${VEX_PEER_RPC_PORT:-18566}"
  VEX_LOCAL_RELEASE_DIR="${VEX_LOCAL_RELEASE_DIR:-}"
  VEX_LOCAL_STRATUM_DIR="${VEX_LOCAL_STRATUM_DIR:-}"
  VEX_POOL_ROOT="${VEX_POOL_ROOT:-/opt/vexon-pool}"
  VEX_BIN_DIR="${VEX_BIN_DIR:-$VEX_POOL_ROOT/bin}"
  VEX_WEB_DIR="${VEX_WEB_DIR:-$VEX_POOL_ROOT/web}"
  VEX_DOCS_DIR="${VEX_DOCS_DIR:-$VEX_POOL_ROOT/docs}"
  VEX_STRATUM_DIR="${VEX_STRATUM_DIR:-$VEX_POOL_ROOT/stratum}"
  VEX_STRATUM_CONFIG_DIR="${VEX_STRATUM_CONFIG_DIR:-$VEX_POOL_ROOT/stratum-config}"
  VEX_CONFIGURE_NGINX="${VEX_CONFIGURE_NGINX:-0}"

  check_env_value POOL_DOMAIN
  check_env_value VEX_DOCS_DOMAIN
  check_env_value POOL_SITE_NAME
  check_env_value POOL_ADMIN_EMAIL
  check_env_value POOL_DB_PASSWORD
  check_env_value STRATUM_DB_PASSWORD
  check_env_value STRATUM_TCP_PASSWORD
  check_env_value VEX_ADDRESS
  check_env_value VEX_RPC_USER
  check_env_value VEX_RPC_PASSWORD
  check_env_value VEX_WALLET_RPC_USER
  check_env_value VEX_WALLET_RPC_PASSWORD

  if [[ "$VEX_START_WALLET" == "1" ]]; then
    if [[ -n "$VEX_WALLET_PASSPHRASE" ]]; then
      ok "VEX_WALLET_PASSPHRASE is set for wallet automation"
    else
      fail "VEX_START_WALLET=1 requires VEX_WALLET_PASSPHRASE"
    fi
    env_mode="$(stat -c '%a' .env 2>/dev/null || stat -f '%Lp' .env 2>/dev/null || true)"
    if [[ -n "$env_mode" && "$env_mode" != "600" ]]; then
      warn ".env mode is $env_mode; use chmod 600 .env before storing the wallet passphrase"
    fi
  else
    warn "VEX_START_WALLET=$VEX_START_WALLET; automatic chain payouts stay disabled until wallet RPC is enabled"
  fi

  check_port_number STRATUM_PORT
  check_port_number VEX_P2P_PORT
  check_port_number VEX_RPC_PORT
  check_port_number VEX_WALLET_RPC_PORT
  if [[ "$VEX_ENABLE_LOCAL_PEER" == "1" ]]; then
    check_port_number VEX_PEER_P2P_PORT
    check_port_number VEX_PEER_RPC_PORT
  fi
  check_port_conflict STRATUM_PORT
  [[ "$VEX_MIN_PAYOUT" =~ ^[0-9]+([.][0-9]+)?$ ]] && ok "VEX_MIN_PAYOUT is valid: $VEX_MIN_PAYOUT" || fail "VEX_MIN_PAYOUT must be numeric"
  [[ "$VEX_EARNINGS_CLEAR_DELAY" =~ ^[0-9]+$ ]] && ok "VEX_EARNINGS_CLEAR_DELAY is valid: $VEX_EARNINGS_CLEAR_DELAY" || fail "VEX_EARNINGS_CLEAR_DELAY must be a non-negative integer"
  [[ "$VEX_MATURE_BLOCKS" =~ ^[1-9][0-9]*$ ]] && ok "VEX_MATURE_BLOCKS is valid: $VEX_MATURE_BLOCKS" || fail "VEX_MATURE_BLOCKS must be a positive integer"
  [[ "$VEX_TXFEE" =~ ^[0-9]+([.][0-9]+)?$ ]] && ok "VEX_TXFEE is valid: $VEX_TXFEE" || fail "VEX_TXFEE must be numeric"
  [[ "$VEX_BACKEND_CAN_STOP_NGINX" =~ ^[01]$ ]] && ok "VEX_BACKEND_CAN_STOP_NGINX is valid: $VEX_BACKEND_CAN_STOP_NGINX" || fail "VEX_BACKEND_CAN_STOP_NGINX must be 0 or 1"

  if [[ "$STRATUM_PORT" == "3399" ]]; then
    warn "STRATUM_PORT is 3399. Use 4499 on a shared server unless you intentionally stopped the existing pool on that port."
  fi

  [[ "$VEX_WEB_DIR" != "/var/web" ]] && ok "VEX_WEB_DIR avoids the shared web path: $VEX_WEB_DIR" || fail "VEX_WEB_DIR must not be /var/web on a shared server"
  [[ "$VEX_DOCS_DIR" != "/var/web" ]] && ok "VEX_DOCS_DIR avoids the shared web path: $VEX_DOCS_DIR" || fail "VEX_DOCS_DIR must not be /var/web on a shared server"
  [[ "$VEX_STRATUM_DIR" != "/var/stratum" ]] && ok "VEX_STRATUM_DIR avoids the shared stratum path: $VEX_STRATUM_DIR" || fail "VEX_STRATUM_DIR must not be /var/stratum on a shared server"
  [[ "$VEX_STRATUM_CONFIG_DIR" != "/var/stratum/config" ]] && ok "VEX_STRATUM_CONFIG_DIR avoids the shared stratum config path: $VEX_STRATUM_CONFIG_DIR" || fail "VEX_STRATUM_CONFIG_DIR must not be /var/stratum/config on a shared server"

  if [[ "$VEX_CONFIGURE_NGINX" == "1" ]]; then
    warn "VEX_CONFIGURE_NGINX=1 will install/reload system nginx. Keep it 0 if Baota or another web stack owns port 80."
  else
    ok "system nginx changes are disabled"
  fi

  if [[ -n "${POOL_BACKUP_TAR:-}" ]]; then
    [[ -f "$POOL_BACKUP_TAR" ]] && ok "backup archive exists" || fail "POOL_BACKUP_TAR not found: $POOL_BACKUP_TAR"
  else
    warn "POOL_BACKUP_TAR is empty; install will require a separately created Vexon wallet before production mining"
  fi

  if [[ -n "$VEX_LOCAL_RELEASE_DIR" ]]; then
	    [[ -x "$VEX_LOCAL_RELEASE_DIR/bin/vexond" ]] && ok "local vexond exists" || fail "missing local vexond in $VEX_LOCAL_RELEASE_DIR/bin"
    [[ -x "$VEX_LOCAL_RELEASE_DIR/bin/vexonctl" ]] && ok "local vexonctl exists" || fail "missing local vexonctl in $VEX_LOCAL_RELEASE_DIR/bin"
    [[ -x "$VEX_LOCAL_RELEASE_DIR/bin/vexonwallet" ]] && ok "local vexonwallet exists" || fail "missing local vexonwallet in $VEX_LOCAL_RELEASE_DIR/bin"
  else
    check_repo_ref "Vexon Core" "$VEX_CORE_REPO" "$VEX_CORE_REF"
    check_repo_ref "Vexon Wallet" "$VEX_WALLET_REPO" "$VEX_WALLET_REF"
  fi

  if [[ -n "$VEX_LOCAL_STRATUM_DIR" ]]; then
    [[ -f "$VEX_LOCAL_STRATUM_DIR/Makefile" ]] && ok "local Vexon Stratum source exists" || fail "missing local Vexon Stratum source in $VEX_LOCAL_STRATUM_DIR"
  else
    check_repo_ref "Vexon Stratum" "$VEX_STRATUM_REPO" "$VEX_STRATUM_REF"
  fi
fi

bash -n install.sh && ok "install.sh syntax"
bash -n scripts/backup-existing-pool.sh && ok "backup script syntax"
bash -n scripts/start-pool.sh && ok "start script syntax"
bash -n scripts/start-wallet-rpc.sh && ok "wallet RPC start script syntax"
bash -n scripts/stop-pool.sh && ok "stop script syntax"
bash -n scripts/status.sh && ok "status script syntax"
bash -n scripts/deploy-web.sh && ok "web deploy script syntax"
bash -n scripts/doctor.sh && ok "doctor script syntax"
bash -n scripts/install-https.sh && ok "https script syntax"
bash -n scripts/install-ops.sh && ok "operations installer syntax"
bash -n scripts/health-check.sh && ok "health check script syntax"
bash -n scripts/miner-watch.sh && ok "miner watch script syntax"
bash -n scripts/monitor-pool.sh && ok "pool monitor script syntax"
bash -n scripts/payout-status.sh && ok "payout status script syntax"
bash -n scripts/payout-closed-loop-check.sh && ok "payout closed-loop script syntax"
bash -n scripts/repair-vex-coin.sh && ok "VEX coin repair script syntax"
bash -n scripts/repair-miner-address.sh && ok "miner address repair script syntax"
bash -n scripts/probe-miner-submit.sh && ok "miner submit probe script syntax"
bash -n scripts/backup-production.sh && ok "production backup script syntax"
bash -n scripts/run-backup.sh && ok "scheduled backup script syntax"
bash -n scripts/run-wallet-rpc-systemd.sh && ok "systemd wallet runner syntax"
bash -n scripts/ssl-renew-check.sh && ok "SSL renewal script syntax"
bash -n scripts/install-systemd.sh && ok "systemd script syntax"
bash -n scripts/audit-vexon-clean.sh && ok "clean deployment audit syntax"

if scripts/audit-vexon-clean.sh >/tmp/vexon-clean-audit.out 2>&1; then
  ok "clean Vexon deployment audit"
else
  cat /tmp/vexon-clean-audit.out >&2 || true
  fail "clean Vexon deployment audit failed"
fi

if (( failures > 0 )); then
  echo "Preflight failed with $failures issue(s)." >&2
  exit 1
fi

echo "Preflight passed."
