#!/usr/bin/env bash
# Th0rn BTX Pool — установщик майнера (GPU rig)
#
# Использование:
#   curl -fsSL https://files.th0rn.ru/files/btx/install.sh | bash
#   curl -fsSL https://files.th0rn.ru/files/btx/install.sh | bash -s -- \
#       --address 'btx1zYOUR_ADDRESS' --pool btx.th0rn.space:3333
#   curl -fsSL ... | bash -s -- --address 'btx1z...' --solo
#
# Что делает:
#   1. Проверяет NVIDIA GPU + Python 3.10+
#   2. Ставит dexbtx-miner (временно, до своего Th0rn miner)
#   3. Скачивает btx-gbt-solve с files.th0rn.ru (SHA256 pin)
#   4. Пишет ~/.btx-miner/config.yaml на пул Th0rn
#   5. Smoke-test CUDA + --daemon
#
# Переменные окружения:
#   BTX_FILES_BASE   — база файлов (default: https://files.th0rn.ru/files/btx)
#   BTX_POOL         — host:port (default: btx.th0rn.space:3333)
#   BTX_SOLVER_SHA256 — override SHA256 solver-бинарника

set -euo pipefail

INSTALL_SH_VERSION="1.0.0"
FILES_BASE="${BTX_FILES_BASE:-https://files.th0rn.ru/files/btx}"
DEFAULT_POOL="${BTX_POOL:-btx.th0rn.space:3333}"
SOLVER_SHA256="${BTX_SOLVER_SHA256:-dcef2c8180b621003053fbc1a7dc58275a2f81794dd405d5b10bc1bad6bb8cd9}"
# dexbtx-miner wrapper (временно, пока не свой Th0rn miner)
MINER_PKG_URL="${BTX_MINER_PKG_URL:-https://github.com/dexbtx/minebtx/archive/refs/tags/v0.4.6.tar.gz}"
# fallback solver, если files.th0rn.ru недоступен
FALLBACK_SOLVER_URL="${BTX_FALLBACK_SOLVER_URL:-https://github.com/dexbtx/minebtx/releases/download/btx-prebuilds-v0.32.3/btx-gbt-solve}"

INSTALL_DIR="${HOME}/.btx-miner"
SOLVER_PATH="${INSTALL_DIR}/bin/btx-gbt-solve"
CONFIG_PATH="${INSTALL_DIR}/config.yaml"
LOG_PATH="${INSTALL_DIR}/miner.log"

ADDRESS=""
WORKER=""
POOL="${DEFAULT_POOL}"
SOLO=0
ASSUME_YES=0
SKIP_PROMPT=0
LOCAL_SOLVER=""

while [[ $# -gt 0 ]]; do
    case "$1" in
        --address) ADDRESS="$2"; shift 2 ;;
        --worker)  WORKER="$2";  shift 2 ;;
        --pool)    POOL="$2";    shift 2 ;;
        --solo)    SOLO=1; POOL="${BTX_POOL:-btx.th0rn.space:3334}"; shift ;;
        --yes|-y)  ASSUME_YES=1; SKIP_PROMPT=1; shift ;;
        --skip-prompt) SKIP_PROMPT=1; shift ;;
        --local-solver) LOCAL_SOLVER="$2"; shift 2 ;;
        --help|-h)
            sed -n '2,18p' "$0"
            echo "  --solo          solo mining (port 3334)"
            exit 0
            ;;
        *) echo "неизвестный аргумент: $1"; exit 1 ;;
    esac
done

if [[ "$SOLO" -eq 1 && "$POOL" == *":3333" && -z "${BTX_POOL:-}" ]]; then
    POOL="${POOL%:*}:3334"
fi

log()  { echo -e "\033[1;36m[th0rn-btx]\033[0m $*"; }
warn() { echo -e "\033[1;33m[warn]\033[0m $*" >&2; }
err()  { echo -e "\033[1;31m[error]\033[0m $*" >&2; exit 1; }

need() { command -v "$1" >/dev/null 2>&1 || err "нет утилиты: $1"; }

sha256_of() {
    if command -v sha256sum >/dev/null 2>&1; then
        sha256sum "$1" | awk '{print $1}'
    else
        shasum -a 256 "$1" | awk '{print $1}'
    fi
}

log "Th0rn BTX miner installer v${INSTALL_SH_VERSION}"
log "пул по умолчанию: ${POOL}"

OS="$(uname -s)"
ARCH="$(uname -m)"
[[ "$OS" == "Linux" ]] || err "поддерживается только Linux (GPU rig)"
[[ "$ARCH" == "x86_64" || "$ARCH" == "amd64" ]] || err "пока только x86_64; arch=$ARCH"

need curl
HAS_NVIDIA=0
GPU_NAME=""
if command -v nvidia-smi >/dev/null 2>&1; then
    if nvidia-smi --query-gpu=name --format=csv,noheader 2>/dev/null | head -1 | grep -q "."; then
        HAS_NVIDIA=1
        GPU_NAME="$(nvidia-smi --query-gpu=name --format=csv,noheader | head -1 | tr -d ' ')"
        log "GPU: ${GPU_NAME}"
    fi
fi
[[ "$HAS_NVIDIA" -eq 1 ]] || warn "NVIDIA GPU не найдена — будет CPU (очень медленно)"

PYTHON=""
for cand in python3.11 python3.10 python3; do
    if command -v "$cand" >/dev/null 2>&1 && "$cand" -c 'import sys; sys.exit(0 if sys.version_info >= (3,10) else 1)'; then
        PYTHON="$cand"
        break
    fi
done
if [[ -z "$PYTHON" ]]; then
    if command -v apt-get >/dev/null 2>&1; then
        log "ставлю python3..."
        sudo apt-get update -qq
        sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq python3 python3-pip python3-venv
        PYTHON=python3
    else
        err "нужен Python 3.10+"
    fi
fi
log "Python: $($PYTHON --version 2>&1)"

if ! "$PYTHON" -m pip --version >/dev/null 2>&1; then
    sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq python3-pip 2>/dev/null || true
fi

pip_install() {
    local elog; elog="$(mktemp)"
    if "$PYTHON" -m pip install --user "$@" 2>"$elog"; then
        rm -f "$elog"; return 0
    fi
    if grep -q "externally-managed-environment" "$elog"; then
        rm -f "$elog"
        "$PYTHON" -m pip install --user --break-system-packages "$@"
    else
        cat "$elog" >&2; rm -f "$elog"; return 1
    fi
}

log "ставлю зависимости (pyyaml)..."
pip_install --quiet --upgrade pyyaml

log "ставлю dexbtx-miner (временный клиент, позже заменим на Th0rn miner)..."
pip_install --quiet --upgrade "$MINER_PKG_URL"

USER_BIN="$("$PYTHON" -m site --user-base 2>/dev/null)/bin"
if ! command -v dexbtx-miner >/dev/null 2>&1; then
    export PATH="${USER_BIN}:$PATH"
fi
command -v dexbtx-miner >/dev/null 2>&1 || warn "dexbtx-miner не в PATH — добавь: export PATH=\"${USER_BIN}:\$PATH\""

mkdir -p "${INSTALL_DIR}/bin"
TMP="$(mktemp)"
trap 'rm -f "$TMP"' EXIT

if [[ -n "$LOCAL_SOLVER" ]]; then
    log "solver из локального файла: ${LOCAL_SOLVER}"
    cp "$LOCAL_SOLVER" "$TMP"
else
    SOLVER_URL="${FILES_BASE}/btx-gbt-solve"
    log "скачиваю btx-gbt-solve → ${SOLVER_URL}"
    if ! curl -fsSL --connect-timeout 15 --max-time 600 "$SOLVER_URL" -o "$TMP"; then
        warn "files.th0rn.ru недоступен, fallback → GitHub prebuilds"
        curl -fsSL --connect-timeout 15 --max-time 600 "$FALLBACK_SOLVER_URL" -o "$TMP"
    fi
fi

ACTUAL_SHA="$(sha256_of "$TMP")"
if [[ "$ACTUAL_SHA" != "$SOLVER_SHA256" ]]; then
    err "SHA256 solver не совпал!\n  ожидали: $SOLVER_SHA256\n  получили: $ACTUAL_SHA\n  Обнови pin в install.sh или проверь файл на files.th0rn.ru"
fi
log "SHA256 solver OK"

install -m 0755 "$TMP" "$SOLVER_PATH"
log "solver → $SOLVER_PATH"

HELP_OUT="$("$SOLVER_PATH" --help 2>&1 || true)"
echo "$HELP_OUT" | grep -q "share-target" || err "solver без --share-target (нужен patched btx-gbt-solve)"
echo "$HELP_OUT" | grep -q "daemon" || err "solver без --daemon (нужен patched btx-gbt-solve)"
log "solver flags: --share-target, --daemon ✓"

if [[ -z "$ADDRESS" && "$SKIP_PROMPT" -eq 0 ]]; then
    echo
    echo "BTX payout-адрес (btx1z…):"
    read -rp "  address: " ADDRESS
fi
[[ -n "$ADDRESS" ]] || warn "адрес не задан — укажи payout_address в ${CONFIG_PATH}"

if [[ -z "$WORKER" ]]; then
    WORKER="$(hostname -s 2>/dev/null || echo rig1)"
fi

if [[ "$HAS_NVIDIA" -eq 1 ]]; then
    SOLVER_BACKEND="cuda"
    # Universal profile (minebtx TUNING.md): workers=16 threads=8 batch=128.
    # НЕ масштабировать threads от nproc — иначе GPU ~60W вместо 400W+.
    SOLVER_THREADS=8
    GPU_BATCH=128
    GPU_PREFETCH=8
    GPU_WORKERS=16
else
    SOLVER_BACKEND="cpu"
    SOLVER_THREADS="$(nproc 2>/dev/null || echo 4)"
    GPU_BATCH=64
    GPU_PREFETCH=4
    GPU_WORKERS=4
fi

if [[ -f "$CONFIG_PATH" && "$ASSUME_YES" -ne 1 ]]; then
    log "config уже есть: $CONFIG_PATH (не перезаписываю; --yes чтобы обновить)"
else
    [[ -f "$CONFIG_PATH" ]] && cp "$CONFIG_PATH" "${CONFIG_PATH}.bak.$(date +%s)"
    POOL_HOST="${POOL%:*}"
    POOL_PORT="${POOL##*:}"
    cat > "$CONFIG_PATH" <<YAML
# Th0rn BTX Pool — miner config (install.sh v${INSTALL_SH_VERSION})
pool_host: "${POOL_HOST}"
pool_port: ${POOL_PORT}
pool_tls: false

payout_address: "${ADDRESS}"
worker_name: "${WORKER}"

gbt_solve_path: "${SOLVER_PATH}"

solver_backend: "${SOLVER_BACKEND}"
solver_threads: ${SOLVER_THREADS}
solver_batch_size: ${GPU_BATCH}
solver_prefetch_depth: ${GPU_PREFETCH}
solver_prepare_workers: ${GPU_WORKERS}
solver_pipeline_async: 1
gpu_inputs: 0

nonces_per_slice: 20000000
solver_max_seconds_per_slice: 5.0
reconnect_initial_s: 1.0
reconnect_max_s: 60.0
log_level: INFO
YAML
    log "config → $CONFIG_PATH"
fi

if [[ "$HAS_NVIDIA" -eq 1 ]]; then
    log "CUDA daemon smoke-test (~10 сек)..."
    DAEMON_JSON='{"version":536870912,"prev_hash":"0ab38fdff2ef667dcddac7f50c3696080c26697615f7b6b9af5c3a1ba0a5fb7e","merkle_root":"d906f02ed11d8936770423263b56c5ffe1ea1b15c8a2867afb161adb6fd76eb7","time":1779672814,"bits":"1d17c609","seed_a":"8460daf3ff446cc55a7115de88ee24c8a2bf182eedde43abb9cf4cc94cc209bf","seed_b":"7f2e377616feb92d2e9857cab390595b7d6b8d24373a2da394f8d97197b5f437","block_height":110806,"nonce_start":1,"max_tries":500000,"max_seconds":12,"share_target":"00ffffff00000000000000000000000000000000000000000000000000000000"}'
    SMOKE_OUT="$(echo "$DAEMON_JSON" | BTX_MATMUL_BACKEND=cuda BTX_CUDA_ALLOW_OLDER_GPUS=1 \
        "$SOLVER_PATH" --daemon --backend cuda --solver-threads 4 --batch-size 128 2>/dev/null | tail -1 || true)"
    if [[ -z "$SMOKE_OUT" || "$SMOKE_OUT" != *"found"* ]]; then
        warn "daemon smoke-test: solver ответил, но share не найден за 12с (может быть норма)"
        warn "проверь nvidia-smi во время майнинга — должен быть процесс btx-gbt-solve ~90%+ GPU"
    else
        log "CUDA daemon smoke-test: OK"
    fi
fi

MINER_CMD="dexbtx-miner"
command -v dexbtx-miner >/dev/null 2>&1 || MINER_CMD="${USER_BIN}/dexbtx-miner"
[[ -x "$MINER_CMD" ]] || MINER_CMD="${USER_BIN}/dexbtx-miner"

LAUNCHER="${INSTALL_DIR}/start-miner.sh"
cat > "$LAUNCHER" <<LAUNCH
#!/usr/bin/env bash
exec "${MINER_CMD}" --config "${CONFIG_PATH}" "\$@"
LAUNCH
chmod 0755 "$LAUNCHER"

MODE="PPLNS"
[[ "${POOL##*:}" == "3334" ]] && MODE="Solo"

echo
log "✓ Установка завершена"
echo
echo "  Пул:      ${POOL} (${MODE})"
echo "  Адрес:    ${ADDRESS:-<укажи в config>}"
echo "  Worker:   ${WORKER}"
echo "  GPU:      ${GPU_NAME:-нет}"
echo "  Backend:  ${SOLVER_BACKEND}"
echo "  Config:   ${CONFIG_PATH}"
echo
echo "Запуск:"
echo "  ${LAUNCHER}"
echo "  # или: ${MINER_CMD} --config ${CONFIG_PATH}"
echo
if [[ ":$PATH:" != *":${USER_BIN}:"* ]]; then
    echo "PATH (добавь в ~/.bashrc, если dexbtx-miner не находится):"
    echo "  export PATH=\"${USER_BIN}:\$PATH\""
    echo
fi
echo "Фон (tmux):"
echo "  tmux new -d -s btx '${LAUNCHER} 2>&1 | tee -a ${LOG_PATH}'"
echo "  tmux attach -t btx"
echo
echo "Проверка GPU:"
echo "  watch -n1 nvidia-smi"
echo
echo "Дашборд пула: https://btx.th0rn.space/"
echo "  Solo :3334   PPLNS :3333   fee 1%"
