#!/usr/bin/env bash
# =============================================================================
# Timmy — Bitcoin Core + LND + LNbits automated setup
# Target: macOS, Apple Silicon (M3 Max)
# Mode: mainnet, pruned (~20 GB block storage)
# =============================================================================
set -euo pipefail

BREW="/opt/homebrew/bin/brew"
BITCOIN_DIR="$HOME/Library/Application Support/Bitcoin"
LND_DIR="$HOME/.lnd"
LNBITS_DIR="$HOME/.lnbits"
LAUNCHD_DIR="$HOME/Library/LaunchAgents"
LOG_DIR="$HOME/Library/Logs/timmy-node"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; NC='\033[0m'
info()    { echo -e "${CYAN}[setup]${NC} $*"; }
ok()      { echo -e "${GREEN}[ok]${NC} $*"; }
warn()    { echo -e "${YELLOW}[warn]${NC} $*"; }
die()     { echo -e "${RED}[error]${NC} $*" >&2; exit 1; }

# ─── Guards ──────────────────────────────────────────────────────────────────
[[ "$(uname -s)" == "Darwin" ]] || die "This script is for macOS only."
[[ "$(uname -m)" == "arm64" ]]  || warn "Not Apple Silicon — paths may differ."

command -v "$BREW" &>/dev/null || die "Homebrew not found at $BREW. Install from https://brew.sh"

# ─── Step 1: Packages ────────────────────────────────────────────────────────
info "Installing Bitcoin Core and LND via Homebrew…"
"$BREW" update --quiet
"$BREW" install bitcoin lnd || true   # 'true' so re-runs don't abort on "already installed"

command -v bitcoind &>/dev/null || die "bitcoind not found after install."
command -v lnd     &>/dev/null || die "lnd not found after install."
ok "Bitcoin Core $("$BREW" info --json bitcoin | python3 -c "import sys,json; d=json.load(sys.stdin); print(d[0]['installed'][0]['version'])" 2>/dev/null || bitcoind --version | head -1) installed."
ok "LND $("$BREW" info --json lnd | python3 -c "import sys,json; d=json.load(sys.stdin); print(d[0]['installed'][0]['version'])" 2>/dev/null || lnd --version | head -1) installed."

# ─── Step 2: LNbits (Python) ─────────────────────────────────────────────────
info "Setting up LNbits…"
if ! command -v python3 &>/dev/null; then
  "$BREW" install python3
fi

PYTHON="$(command -v python3)"
PIP="$PYTHON -m pip"

if [[ ! -d "$LNBITS_DIR" ]]; then
  info "Cloning LNbits…"
  git clone --depth 1 https://github.com/lnbits/lnbits.git "$LNBITS_DIR"
else
  info "LNbits already cloned at $LNBITS_DIR"
fi

info "Installing LNbits Python deps (this may take a minute)…"
cd "$LNBITS_DIR"
if command -v uv &>/dev/null; then
  uv pip install --system poetry 2>/dev/null || $PIP install --quiet poetry
else
  $PIP install --quiet poetry 2>/dev/null || true
fi

if command -v poetry &>/dev/null || [[ -f "$HOME/.local/bin/poetry" ]]; then
  POETRY="$(command -v poetry 2>/dev/null || echo "$HOME/.local/bin/poetry")"
  "$POETRY" install --no-root --quiet 2>/dev/null || warn "poetry install had warnings (often OK)"
else
  warn "poetry not found — trying pip install from pyproject.toml…"
  $PIP install --quiet lnbits 2>/dev/null || warn "direct pip install of lnbits failed — check $LNBITS_DIR manually"
fi
cd "$SCRIPT_DIR"
ok "LNbits ready at $LNBITS_DIR"

# ─── Step 3: Directories & Logs ──────────────────────────────────────────────
info "Creating data and log directories…"
mkdir -p "$LOG_DIR" "$LAUNCHD_DIR"

# ─── Step 4: Generate secrets ────────────────────────────────────────────────
SECRETS_FILE="$SCRIPT_DIR/.node-secrets"
if [[ -f "$SECRETS_FILE" ]]; then
  info "Loading existing secrets from $SECRETS_FILE"
  source "$SECRETS_FILE"
else
  info "Generating fresh secrets…"
  RPC_USER="timmy"
  RPC_PASS="$(openssl rand -hex 32)"
  WALLET_PASS="$(openssl rand -hex 24)"
  LND_MACAROON_PASS="$(openssl rand -hex 24)"
  cat > "$SECRETS_FILE" <<EOF
RPC_USER="$RPC_USER"
RPC_PASS="$RPC_PASS"
WALLET_PASS="$WALLET_PASS"
LND_MACAROON_PASS="$LND_MACAROON_PASS"
EOF
  chmod 600 "$SECRETS_FILE"
  ok "Secrets written to $SECRETS_FILE (keep this safe!)"
fi

# ─── Step 5: Bitcoin Core config ─────────────────────────────────────────────
info "Writing Bitcoin Core config…"
mkdir -p "$BITCOIN_DIR"
# Only write if doesn't exist (don't clobber a running node's config)
if [[ ! -f "$BITCOIN_DIR/bitcoin.conf" ]]; then
  cat > "$BITCOIN_DIR/bitcoin.conf" <<EOF
# Timmy node — mainnet, pruned
mainnet=1
server=1
prune=20000

# RPC
rpcuser=$RPC_USER
rpcpassword=$RPC_PASS
rpcallowip=127.0.0.1
rpcbind=127.0.0.1
rpcport=8332

# ZMQ (required by LND)
zmqpubrawblock=tcp://127.0.0.1:28332
zmqpubrawtx=tcp://127.0.0.1:28333

# Performance
dbcache=4096
maxmempool=512
maxconnections=24
listen=1

# Logging (keep it manageable)
debug=0
shrinkdebugfile=1
EOF
  ok "bitcoin.conf written."
else
  ok "bitcoin.conf already exists — leaving untouched."
fi

# ─── Step 6: LND config ──────────────────────────────────────────────────────
info "Writing LND config…"
mkdir -p "$LND_DIR"
if [[ ! -f "$LND_DIR/lnd.conf" ]]; then
  cat > "$LND_DIR/lnd.conf" <<EOF
[Application Options]
debuglevel=info
maxpendingchannels=10
# Expose REST API for LNbits
restlisten=0.0.0.0:8080
rpclisten=0.0.0.0:10009
# Wallet password auto-unlock file (written by start.sh)
wallet-unlock-password-file=$LND_DIR/.wallet-password

[Bitcoin]
bitcoin.active=1
bitcoin.mainnet=1
bitcoin.node=bitcoind

[Bitcoind]
bitcoind.rpchost=127.0.0.1:8332
bitcoind.rpcuser=$RPC_USER
bitcoind.rpcpass=$RPC_PASS
bitcoind.zmqpubrawblock=tcp://127.0.0.1:28332
bitcoind.zmqpubrawtx=tcp://127.0.0.1:28333
bitcoind.estimatemode=ECONOMICAL

[tor]
tor.active=0
EOF
  ok "lnd.conf written."
else
  ok "lnd.conf already exists — leaving untouched."
fi

# Write wallet unlock password file (used by LND auto-unlock)
echo -n "$WALLET_PASS" > "$LND_DIR/.wallet-password"
chmod 600 "$LND_DIR/.wallet-password"

# ─── Step 7: LNbits .env ─────────────────────────────────────────────────────
info "Writing LNbits environment…"
LNBITS_DATA_DIR="$HOME/.lnbits-data"
mkdir -p "$LNBITS_DATA_DIR"

if [[ ! -f "$LNBITS_DATA_DIR/.env" ]]; then
  # Generate a superuser ID for LNbits
  LNBITS_SUPER_USER="$(openssl rand -hex 16)"
  cat > "$LNBITS_DATA_DIR/.env" <<EOF
# LNbits config — Timmy node
LNBITS_DATA_FOLDER=$LNBITS_DATA_DIR
LNBITS_BACKEND_WALLET_CLASS=LndRestWallet
LND_REST_ENDPOINT=https://127.0.0.1:8080
LND_REST_CERT=$LND_DIR/tls.cert
LND_REST_MACAROON=$LND_DIR/data/chain/bitcoin/mainnet/admin.macaroon
LNBITS_SITE_TITLE=Timmy Node
LNBITS_ALLOWED_IPS=127.0.0.1
HOST=127.0.0.1
PORT=5000
FORWARDED_ALLOW_IPS=*
# Uncomment to set a fixed super user (otherwise auto-generated)
# LNBITS_SUPER_USER=$LNBITS_SUPER_USER
EOF
  # Append super user to secrets
  echo "LNBITS_SUPER_USER=\"$LNBITS_SUPER_USER\"" >> "$SECRETS_FILE"
  ok "LNbits .env written to $LNBITS_DATA_DIR/.env"
else
  ok "LNbits .env already exists — leaving untouched."
fi

# ─── Step 8: LaunchAgent plists ──────────────────────────────────────────────
info "Writing LaunchAgent plists (auto-start on login)…"

# Bitcoin Core
cat > "$LAUNCHD_DIR/com.timmy.bitcoind.plist" <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>             <string>com.timmy.bitcoind</string>
  <key>ProgramArguments</key>
  <array>
    <string>/opt/homebrew/bin/bitcoind</string>
    <string>-conf=$HOME/Library/Application Support/Bitcoin/bitcoin.conf</string>
    <string>-datadir=$HOME/Library/Application Support/Bitcoin</string>
    <string>-daemon=0</string>
  </array>
  <key>RunAtLoad</key>         <true/>
  <key>KeepAlive</key>         <true/>
  <key>StandardOutPath</key>   <string>$LOG_DIR/bitcoind.log</string>
  <key>StandardErrorPath</key> <string>$LOG_DIR/bitcoind.err</string>
  <key>EnvironmentVariables</key>
  <dict>
    <key>HOME</key><string>$HOME</string>
  </dict>
</dict>
</plist>
EOF

# LND — starts after bitcoind (bitcoind takes ~30s to be RPC-ready)
cat > "$LAUNCHD_DIR/com.timmy.lnd.plist" <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>             <string>com.timmy.lnd</string>
  <key>ProgramArguments</key>
  <array>
    <string>/opt/homebrew/bin/lnd</string>
    <string>--configfile=$LND_DIR/lnd.conf</string>
    <string>--lnddir=$LND_DIR</string>
  </array>
  <key>RunAtLoad</key>         <true/>
  <key>KeepAlive</key>         <true/>
  <key>StandardOutPath</key>   <string>$LOG_DIR/lnd.log</string>
  <key>StandardErrorPath</key> <string>$LOG_DIR/lnd.err</string>
  <key>EnvironmentVariables</key>
  <dict>
    <key>HOME</key><string>$HOME</string>
  </dict>
</dict>
</plist>
EOF

# LNbits — depends on LND being up
cat > "$LAUNCHD_DIR/com.timmy.lnbits.plist" <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>             <string>com.timmy.lnbits</string>
  <key>ProgramArguments</key>
  <array>
    <string>/bin/bash</string>
    <string>-c</string>
    <string>cd $LNBITS_DIR &amp;&amp; env \$(cat $LNBITS_DATA_DIR/.env | grep -v '^#' | xargs) poetry run lnbits</string>
  </array>
  <key>RunAtLoad</key>         <true/>
  <key>KeepAlive</key>         <true/>
  <key>StandardOutPath</key>   <string>$LOG_DIR/lnbits.log</string>
  <key>StandardErrorPath</key> <string>$LOG_DIR/lnbits.err</string>
  <key>EnvironmentVariables</key>
  <dict>
    <key>HOME</key><string>$HOME</string>
    <key>PATH</key><string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
  </dict>
</dict>
</plist>
EOF

ok "LaunchAgent plists written to $LAUNCHD_DIR"

# ─── Step 9: Load plists ─────────────────────────────────────────────────────
info "Loading LaunchAgents…"
for plist in com.timmy.bitcoind com.timmy.lnd com.timmy.lnbits; do
  launchctl unload "$LAUNCHD_DIR/$plist.plist" 2>/dev/null || true
  launchctl load -w "$LAUNCHD_DIR/$plist.plist"
  ok "$plist loaded."
done

# ─── Step 10: Create LND wallet if needed ─────────────────────────────────────
info "Waiting 15s for LND to start before checking wallet…"
sleep 15

LNCLI="/opt/homebrew/bin/lncli"
if ! "$LNCLI" --lnddir="$LND_DIR" getinfo &>/dev/null; then
  info "LND wallet not yet initialized — creating one now…"
  echo "Wallet password will be: $WALLET_PASS"
  echo "---"
  echo "Run this command in a new terminal:"
  echo ""
  echo "  lncli --lnddir=$LND_DIR create"
  echo ""
  echo "Use password: $WALLET_PASS"
  echo "Choose 'n' for existing seed (new wallet)"
  echo "Save the 24-word seed in a safe place!"
  echo "---"
  warn "After creating the wallet, run: bash $SCRIPT_DIR/get-lnbits-key.sh"
else
  ok "LND wallet already exists and is accessible."
fi

# ─── Done ────────────────────────────────────────────────────────────────────
echo ""
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${GREEN}  Timmy node setup complete!${NC}"
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""
echo "  Bitcoin Core is syncing — this takes 1-3 days (pruned)."
echo "  LND will connect once bitcoind is at chain tip."
echo "  LNbits will be live at http://127.0.0.1:5000 once LND is ready."
echo ""
echo "  Next steps:"
echo "  1. Create your LND wallet:  lncli --lnddir=$LND_DIR create"
echo "  2. Check sync status:       bash $SCRIPT_DIR/status.sh"
echo "  3. Once synced, get key:    bash $SCRIPT_DIR/get-lnbits-key.sh"
echo ""
echo "  LNbits key retrieval (get-lnbits-key.sh):"
echo "  • LNbits < 0.12  — auto-creates a wallet via the superuser API"
echo "  • LNbits >= 0.12 — superuser API removed; script walks you through"
echo "                     the Admin UI at http://localhost:5000/admin"
echo ""
echo "  Secrets are in: $SECRETS_FILE"
echo "  Logs are in:    $LOG_DIR/"
echo ""
