#!/usr/bin/env bash
# ============================================================================
# Knotsday - Bitcoin Knots Complete Setup Script
# https://knotsday.com
#
# This script:
#   1. Prepares an ext4 drive for blockchain storage
#   2. Downloads and installs the latest Bitcoin Knots
#   3. Creates configuration with secure RPC credentials
#   4. Optionally installs ckpool for solo mining
#   5. Sets up systemd services
#
# Usage:
#   chmod +x setup-knots.sh
#   ./setup-knots.sh
#
# ALWAYS read scripts before running them.
# ============================================================================

set -euo pipefail

# --- Configuration ---
KNOTS_VERSION="${KNOTS_VERSION:-29.3.knots20260508}"
KNOTS_URL="https://bitcoinknots.org/files/29.x/${KNOTS_VERSION}/bitcoin-${KNOTS_VERSION}-x86_64-linux-gnu.tar.gz"
INSTALL_DIR="${HOME}/.local/bin"
CONFIG_DIR="${HOME}/.bitcoin"
CKPOOL_CONFIG_DIR="${HOME}/.local/etc"
CKPOOL_LOG_DIR="${HOME}/.local/var/log/ckpool"

# --- Colors ---
RED='\033[0;31m'
GREEN='\033[0;32m'
GOLD='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m'

info()  { echo -e "${BLUE}[INFO]${NC} $*"; }
ok()    { echo -e "${GREEN}[OK]${NC} $*"; }
warn()  { echo -e "${GOLD}[WARN]${NC} $*"; }
err()   { echo -e "${RED}[ERROR]${NC} $*" >&2; }

# --- Helpers ---
confirm() {
    local prompt="${1:-Continue?}"
    read -rp "$(echo -e "${GOLD}${prompt} [y/N]${NC} ")" answer
    [[ "${answer}" =~ ^[Yy]$ ]]
}

generate_password() {
    python3 -c "import secrets; print(secrets.token_hex(32))"
}

# ============================================================================
# Step 1: Drive Preparation
# ============================================================================
prepare_drive() {
    echo ""
    echo "============================================"
    echo "  STEP 1: Prepare Storage Drive"
    echo "============================================"
    echo ""

    info "Available block devices:"
    echo ""
    lsblk -o NAME,SIZE,FSTYPE,MOUNTPOINT,MODEL | grep -v loop
    echo ""

    read -rp "$(echo -e "${GOLD}Enter the device to use (e.g. /dev/sdb): ${NC}")" TARGET_DEVICE

    if [[ ! -b "${TARGET_DEVICE}" ]]; then
        err "Device ${TARGET_DEVICE} does not exist."
        exit 1
    fi

    # Safety check: don't format the system drive
    SYSTEM_DEVICE=$(df / | tail -1 | awk '{print $1}' | sed 's/[0-9]*$//' | sed 's/p[0-9]*$//')
    if [[ "${TARGET_DEVICE}" == "${SYSTEM_DEVICE}" ]]; then
        err "That is your system drive! Refusing to format."
        exit 1
    fi

    warn "This will ERASE ALL DATA on ${TARGET_DEVICE}"
    echo ""
    lsblk -o NAME,SIZE,FSTYPE,MOUNTPOINT "${TARGET_DEVICE}"
    echo ""

    if ! confirm "Are you absolutely sure?"; then
        info "Aborted."
        exit 0
    fi

    info "Unmounting any mounted partitions on ${TARGET_DEVICE}..."
    for part in $(lsblk -ln -o NAME "${TARGET_DEVICE}" | tail -n +2); do
        sudo umount "/dev/${part}" 2>/dev/null || true
    done

    info "Creating GPT partition table..."
    sudo parted -s "${TARGET_DEVICE}" mklabel gpt

    info "Creating ext4 partition..."
    sudo parted -s "${TARGET_DEVICE}" mkpart primary ext4 0% 100%

    # Determine partition name (handles both sdX1 and nvmeXnXp1 formats)
    sleep 1
    PARTITION=$(lsblk -ln -o NAME "${TARGET_DEVICE}" | tail -1)
    PARTITION_PATH="/dev/${PARTITION}"

    info "Formatting ${PARTITION_PATH} as ext4..."
    sudo mkfs.ext4 -L bitcoin "${PARTITION_PATH}"

    # Mount
    MOUNT_POINT="/media/${USER}/bitcoin"
    sudo mkdir -p "${MOUNT_POINT}"
    sudo mount "${PARTITION_PATH}" "${MOUNT_POINT}"
    sudo chown "${USER}:${USER}" "${MOUNT_POINT}"

    # Add to fstab
    UUID=$(sudo blkid -s UUID -o value "${PARTITION_PATH}")
    if ! grep -q "${UUID}" /etc/fstab 2>/dev/null; then
        info "Adding to /etc/fstab for auto-mount..."
        echo "UUID=${UUID} ${MOUNT_POINT} ext4 defaults,noatime 0 2" | sudo tee -a /etc/fstab
    fi

    DATADIR="${MOUNT_POINT}/.bitcoin"
    mkdir -p "${DATADIR}"

    ok "Drive prepared: ${PARTITION_PATH} mounted at ${MOUNT_POINT}"
    echo ""
}

# ============================================================================
# Step 2: Install Bitcoin Knots
# ============================================================================
install_knots() {
    echo ""
    echo "============================================"
    echo "  STEP 2: Install Bitcoin Knots"
    echo "============================================"
    echo ""

    mkdir -p "${INSTALL_DIR}"

    # Check if already installed
    if command -v bitcoind &>/dev/null; then
        CURRENT=$(bitcoind --version | head -1)
        info "Currently installed: ${CURRENT}"
        if ! confirm "Install/update to ${KNOTS_VERSION}?"; then
            return
        fi
    fi

    info "Downloading Bitcoin Knots ${KNOTS_VERSION}..."
    cd /tmp
    wget -q --show-progress "${KNOTS_URL}"

    info "Extracting..."
    tar xzf "bitcoin-${KNOTS_VERSION}-x86_64-linux-gnu.tar.gz"

    info "Installing to ${INSTALL_DIR}..."
    cp "bitcoin-${KNOTS_VERSION}/bin/bitcoin-cli" "${INSTALL_DIR}/"
    cp "bitcoin-${KNOTS_VERSION}/bin/bitcoind" "${INSTALL_DIR}/"
    cp "bitcoin-${KNOTS_VERSION}/bin/bitcoin-qt" "${INSTALL_DIR}/"
    cp "bitcoin-${KNOTS_VERSION}/bin/bitcoin-tx" "${INSTALL_DIR}/"
    cp "bitcoin-${KNOTS_VERSION}/bin/bitcoin-util" "${INSTALL_DIR}/"
    cp "bitcoin-${KNOTS_VERSION}/bin/bitcoin-wallet" "${INSTALL_DIR}/"

    # Clean up
    rm -rf "bitcoin-${KNOTS_VERSION}" "bitcoin-${KNOTS_VERSION}-x86_64-linux-gnu.tar.gz"

    # Ensure ~/.local/bin is in PATH
    if ! echo "${PATH}" | grep -q "${INSTALL_DIR}"; then
        warn "${INSTALL_DIR} is not in your PATH."
        echo "export PATH=\"${INSTALL_DIR}:\${PATH}\"" >> "${HOME}/.bashrc"
        export PATH="${INSTALL_DIR}:${PATH}"
        ok "Added to ~/.bashrc"
    fi

    ok "Bitcoin Knots ${KNOTS_VERSION} installed."
    "${INSTALL_DIR}/bitcoind" --version | head -1
    echo ""
}

# ============================================================================
# Step 3: Configure
# ============================================================================
configure_knots() {
    echo ""
    echo "============================================"
    echo "  STEP 3: Configure Bitcoin Knots"
    echo "============================================"
    echo ""

    mkdir -p "${CONFIG_DIR}"

    if [[ -f "${CONFIG_DIR}/bitcoin.conf" ]]; then
        warn "bitcoin.conf already exists."
        if ! confirm "Overwrite?"; then
            return
        fi
        cp "${CONFIG_DIR}/bitcoin.conf" "${CONFIG_DIR}/bitcoin.conf.bak"
        info "Backed up to bitcoin.conf.bak"
    fi

    # Generate RPC credentials
    RPC_USER="knotsrpc"
    RPC_PASS=$(generate_password)

    # Determine datadir
    if [[ -z "${DATADIR:-}" ]]; then
        read -rp "$(echo -e "${GOLD}Enter blockchain data directory [/media/${USER}/bitcoin/.bitcoin]: ${NC}")" DATADIR
        DATADIR="${DATADIR:-/media/${USER}/bitcoin/.bitcoin}"
    fi

    mkdir -p "${DATADIR}"

    cat > "${CONFIG_DIR}/bitcoin.conf" <<EOF
# Bitcoin Knots Configuration
# Generated by Knotsday setup script

# Blockchain data on ext4 drive
datadir=${DATADIR}

# Run as a daemon
daemon=1

# Full transaction index
txindex=1

# UTXO statistics index
coinstatsindex=1

# RPC server
server=1
rpcuser=${RPC_USER}
rpcpassword=${RPC_PASS}

# Reject replace-by-fee abuse
mempoolreplacement=0

# Performance (lower dbcache to 1000 after initial sync)
dbcache=4000
rpcworkqueue=128
rpcthreads=8
EOF

    ok "bitcoin.conf created."
    echo ""
    info "RPC Credentials (save these!):"
    echo "  rpcuser=${RPC_USER}"
    echo "  rpcpassword=${RPC_PASS}"
    echo ""
    warn "You will need these credentials for ckpool and bitcoin-cli."
    echo ""
}

# ============================================================================
# Step 4: Install ckpool (optional)
# ============================================================================
install_ckpool() {
    echo ""
    echo "============================================"
    echo "  STEP 4: Install ckpool (Solo Mining)"
    echo "============================================"
    echo ""

    if ! confirm "Install ckpool for solo mining?"; then
        info "Skipping ckpool installation."
        return
    fi

    info "Installing build dependencies..."
    sudo apt-get update -qq
    sudo apt-get install -y -qq build-essential autoconf automake \
        libtool pkg-config libssl-dev

    info "Cloning ckpool..."
    cd /tmp
    rm -rf ckpool
    git clone https://bitbucket.org/ckolivas/ckpool.git
    cd ckpool

    info "Building..."
    ./autogen.sh
    ./configure
    make -j"$(nproc)"

    info "Installing..."
    cp src/ckpool src/notifier "${INSTALL_DIR}/"

    # Clean up
    cd /tmp
    rm -rf ckpool

    # Configure
    mkdir -p "${CKPOOL_CONFIG_DIR}" "${CKPOOL_LOG_DIR}"

    read -rp "$(echo -e "${GOLD}Enter your Bitcoin wallet address: ${NC}")" BTC_ADDRESS

    if [[ -z "${BTC_ADDRESS}" ]]; then
        err "Wallet address is required for mining."
        exit 1
    fi

    # Read RPC credentials from bitcoin.conf
    CONF_RPC_USER=$(grep "^rpcuser=" "${CONFIG_DIR}/bitcoin.conf" | cut -d= -f2)
    CONF_RPC_PASS=$(grep "^rpcpassword=" "${CONFIG_DIR}/bitcoin.conf" | cut -d= -f2)

    cat > "${CKPOOL_CONFIG_DIR}/ckpool.conf" <<EOF
{
    "btcd" : [
        {
            "url" : "localhost:8332",
            "auth" : "${CONF_RPC_USER}",
            "pass" : "${CONF_RPC_PASS}"
        }
    ],
    "btcaddress" : "${BTC_ADDRESS}",
    "btcsignet" : false,
    "serverurl" : [
        "0.0.0.0:3333"
    ],
    "mindiff" : 1,
    "startdiff" : 1000,
    "logdir" : "${CKPOOL_LOG_DIR}"
}
EOF

    # Systemd service
    mkdir -p "${HOME}/.config/systemd/user"

    cat > "${HOME}/.config/systemd/user/ckpool.service" <<EOF
[Unit]
Description=CKPool Solo Mining Proxy
After=network-online.target
Wants=network-online.target

[Service]
ExecStart=${INSTALL_DIR}/ckpool -B -c ${CKPOOL_CONFIG_DIR}/ckpool.conf
Restart=on-failure
RestartSec=10

[Install]
WantedBy=default.target
EOF

    systemctl --user daemon-reload
    systemctl --user enable ckpool.service

    loginctl enable-linger "${USER}"

    ok "ckpool installed and configured."
    info "Start with: systemctl --user start ckpool"
    echo ""
}

# ============================================================================
# Step 5: Start
# ============================================================================
start_node() {
    echo ""
    echo "============================================"
    echo "  STEP 5: Start Bitcoin Knots"
    echo "============================================"
    echo ""

    if confirm "Start Bitcoin Knots now?"; then
        info "Starting bitcoin-qt..."
        bitcoin-qt &
        disown

        info "Waiting for RPC to become available..."
        for i in $(seq 1 30); do
            if bitcoin-cli -rpcuser="${RPC_USER:-knotsrpc}" \
                -rpcpassword="${RPC_PASS:-}" \
                getblockchaininfo &>/dev/null 2>&1; then
                ok "Node is running!"
                bitcoin-cli -rpcuser="${RPC_USER}" \
                    -rpcpassword="${RPC_PASS}" \
                    getblockchaininfo | head -8
                break
            fi
            sleep 2
        done

        echo ""
        info "The node is syncing. This will take several hours."
        info "You can check progress with:"
        echo "  bitcoin-cli -rpcuser=${RPC_USER} -rpcpassword=YOUR_PASSWORD getblockchaininfo"
    fi
}

# ============================================================================
# Main
# ============================================================================
main() {
    echo ""
    echo "  ================================================"
    echo "    KNOTSDAY - Bitcoin Knots Setup"
    echo "    September 12, 1683"
    echo "    Venimus, Vidimus, Deus Vicit"
    echo "  ================================================"
    echo ""

    # Check Ubuntu
    if ! command -v apt-get &>/dev/null; then
        err "This script is designed for Ubuntu/Debian systems."
        exit 1
    fi

    # Menu
    echo "  What would you like to do?"
    echo ""
    echo "  1) Full setup (drive + knots + ckpool)"
    echo "  2) Install/update Bitcoin Knots only"
    echo "  3) Prepare drive only"
    echo "  4) Install ckpool only"
    echo ""
    read -rp "$(echo -e "${GOLD}Choose [1-4]: ${NC}")" choice

    case "${choice}" in
        1)
            prepare_drive
            install_knots
            configure_knots
            install_ckpool
            start_node
            ;;
        2)
            install_knots
            ;;
        3)
            prepare_drive
            ;;
        4)
            install_ckpool
            ;;
        *)
            err "Invalid choice."
            exit 1
            ;;
    esac

    echo ""
    echo "  ================================================"
    echo "    Setup complete."
    echo "    The siege will be broken."
    echo "  ================================================"
    echo ""
}

main "$@"
