#!/usr/bin/env bash
# install.sh — Seismic testnet RPC node installer
#
# Usage:
#   curl -fsSL https://install.seismictest.net | bash
#
# Override knobs (set before piping or with env -i):
#   SEISMIC_USER                   service user; defaults to $SUDO_USER or system 'seismic'
#   SEISMIC_DATA_DIR=/var/lib/seismic
#   SEISMIC_NETWORK_JSON_URL       override network config URL (test/staging)
#   SEISMIC_INSTALL_URL            override base URL for fetching libexec/ and templates/
#   SEISMIC_INSTALLER_LOCAL_DIR    point at a local checkout instead of fetching
#   SEISMIC_FORCE                  skip "already installed" prompt
#   SEISMIC_FORCE_REBUILD          force re-clone+rebuild
#   SEISMIC_SUMMIT_REF / SEISMIC_RETH_REF  override git refs from network.json
#   SEISMIC_SKIP_RAM_CHECK / SEISMIC_SKIP_DISK_CHECK   bypass RAM/disk preflights

set -euo pipefail
IFS=$'\n\t'

# ---------- Bootstrap: get libexec/ and templates/ available locally ----------

: "${SEISMIC_INSTALL_URL:=https://install.seismictest.net}"
: "${SEISMIC_INSTALL_LOG:=/var/log/seismic-install.log}"

bootstrap_log() { printf "==> %s\n" "$*"; }
bootstrap_die() { printf "error: %s\n" "$*" >&2; exit 1; }

# Resolve where to load libexec/ from: explicit local dir > sibling of this script > download.
if [[ -n "${SEISMIC_INSTALLER_LOCAL_DIR:-}" && -d "$SEISMIC_INSTALLER_LOCAL_DIR/libexec" ]]; then
    SEISMIC_INSTALLER_ROOT="$SEISMIC_INSTALLER_LOCAL_DIR"
elif [[ -n "${BASH_SOURCE[0]:-}" && -f "${BASH_SOURCE[0]}" ]]; then
    _self="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    if [[ -d "$_self/libexec" ]]; then
        SEISMIC_INSTALLER_ROOT="$_self"
    fi
fi

if [[ -z "${SEISMIC_INSTALLER_ROOT:-}" ]]; then
    SEISMIC_INSTALLER_ROOT="$(mktemp -d)"
    trap 'rm -rf "$SEISMIC_INSTALLER_ROOT"' EXIT
    bootstrap_log "downloading installer assets to $SEISMIC_INSTALLER_ROOT"
    mkdir -p "$SEISMIC_INSTALLER_ROOT/libexec" "$SEISMIC_INSTALLER_ROOT/templates"
    for f in common.sh preflight.sh configure.sh deps.sh data_dir.sh keys.sh network_json.sh build.sh systemd.sh; do
        if ! curl -fsSL --max-time 30 "$SEISMIC_INSTALL_URL/libexec/$f" -o "$SEISMIC_INSTALLER_ROOT/libexec/$f"; then
            bootstrap_die "failed to download libexec/$f from $SEISMIC_INSTALL_URL"
        fi
    done
    for t in seismic-reth.service seismic-summit.service env.example; do
        if ! curl -fsSL --max-time 30 "$SEISMIC_INSTALL_URL/templates/$t" -o "$SEISMIC_INSTALLER_ROOT/templates/$t"; then
            bootstrap_die "failed to download templates/$t from $SEISMIC_INSTALL_URL"
        fi
    done
fi
export SEISMIC_INSTALLER_ROOT

# ---------- Source helpers ----------

# shellcheck source=libexec/common.sh
. "$SEISMIC_INSTALLER_ROOT/libexec/common.sh"
# shellcheck source=libexec/preflight.sh
. "$SEISMIC_INSTALLER_ROOT/libexec/preflight.sh"
# shellcheck source=libexec/configure.sh
. "$SEISMIC_INSTALLER_ROOT/libexec/configure.sh"
# shellcheck source=libexec/deps.sh
. "$SEISMIC_INSTALLER_ROOT/libexec/deps.sh"
# shellcheck source=libexec/data_dir.sh
. "$SEISMIC_INSTALLER_ROOT/libexec/data_dir.sh"
# shellcheck source=libexec/keys.sh
. "$SEISMIC_INSTALLER_ROOT/libexec/keys.sh"
# shellcheck source=libexec/network_json.sh
. "$SEISMIC_INSTALLER_ROOT/libexec/network_json.sh"
# shellcheck source=libexec/build.sh
. "$SEISMIC_INSTALLER_ROOT/libexec/build.sh"
# shellcheck source=libexec/systemd.sh
. "$SEISMIC_INSTALLER_ROOT/libexec/systemd.sh"

# ---------- Output mirroring + error trap ----------

# Ensure log file exists and is writable, even before we know we have sudo.
if [[ ! -w "$(dirname "$SEISMIC_INSTALL_LOG")" ]]; then
    SEISMIC_INSTALL_LOG="${TMPDIR:-/tmp}/seismic-install.log"
fi
touch "$SEISMIC_INSTALL_LOG" 2>/dev/null || SEISMIC_INSTALL_LOG="${TMPDIR:-/tmp}/seismic-install.log"
exec > >(tee -a "$SEISMIC_INSTALL_LOG") 2>&1

on_error() {
    local exit_code=$? line=$1
    printf "\n%serror%s installer failed at line %s (exit %s).\n" "${RED}${BOLD}" "${RESET}" "$line" "$exit_code" >&2
    printf "       full log: %s\n" "$SEISMIC_INSTALL_LOG" >&2
    exit "$exit_code"
}
trap 'on_error $LINENO' ERR

# ---------- Main ----------

main() {
    info "Seismic RPC node installer"
    info "log: $SEISMIC_INSTALL_LOG"
    info "install URL: $SEISMIC_INSTALL_URL"
    info "network config: $SEISMIC_NETWORK_JSON_URL"

    preflight_run_all

    configure_node_interactive

    data_dir_resolve_user
    data_dir_create

    deps_install_apt
    network_json_fetch
    network_json_fetch_genesis
    deps_install_rust

    keys_provision_reth_p2p

    build_summit
    build_reth

    keys_provision_summit_consensus

    systemd_render_env_file
    install_cli
    install_installer_assets
    systemd_install_units

    print_next_steps
}

# Install seismic-node CLI to /usr/local/bin
install_cli() {
    step "installing seismic-node CLI"
    local src
    if [[ -f "$SEISMIC_INSTALLER_ROOT/seismic-node" ]]; then
        src="$SEISMIC_INSTALLER_ROOT/seismic-node"
    else
        src="$(mktemp)"
        if ! curl -fsSL --max-time 30 "$SEISMIC_INSTALL_URL/seismic-node" -o "$src"; then
            die "failed to download seismic-node from $SEISMIC_INSTALL_URL/seismic-node"
        fi
    fi
    $SUDO install -m 755 -o root -g root "$src" "$SEISMIC_CLI_PATH"
    [[ "$src" == "$SEISMIC_INSTALLER_ROOT/seismic-node" ]] || rm -f "$src"
    ok "seismic-node installed at $SEISMIC_CLI_PATH"
}

# Stash libexec/ + templates/ on disk so seismic-node can use them later (e.g. for setup-ssl).
install_installer_assets() {
    local target=/usr/local/share/seismic-installer
    $SUDO install -d -m 755 "$target/libexec" "$target/templates"
    $SUDO cp -r "$SEISMIC_INSTALLER_ROOT/libexec/." "$target/libexec/"
    $SUDO cp -r "$SEISMIC_INSTALLER_ROOT/templates/." "$target/templates/"
    if [[ -f "$NETWORK_JSON_PATH" ]]; then
        :  # already installed by network_json_fetch
    fi
}

print_next_steps() {
    local mode_line="Mode:            standard (full consensus)"
    if [[ -n "${SEISMIC_OBSERVER_NUM:-}" ]]; then
        mode_line="Mode:            observer #$SEISMIC_OBSERVER_NUM"
    fi
    cat <<EOF

${GREEN}${BOLD}Installation complete.${RESET}

Next steps:

  ${BOLD}Start the node:${RESET}
    sudo seismic-node start

  ${BOLD}Watch logs:${RESET}
    sudo seismic-node logs reth -f
    sudo seismic-node logs summit -f

  ${BOLD}Check status:${RESET}
    sudo seismic-node status

  ${BOLD}Stop the node:${RESET}
    sudo seismic-node stop

$mode_line
Service user:    $SEISMIC_USER
Data directory:  $SEISMIC_DATA_DIR
Config:          $SEISMIC_CONFIG_DIR
Binaries:        $SEISMIC_BIN_DIR
Install log:     $SEISMIC_INSTALL_LOG

For help: seismic-node --help
EOF
}

main "$@"
